选择显示字体大小

.net设计模式研究之装饰模式

概述

  在软件系统中,有时候我们会使用继承来扩展对象的功能,但是由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?这就是本文要讲的decorator模式

  意图

  动态地给一个对象添加一些额外的职责。就增加功能来说,decorator模式相比生成子类更为灵活。[gof 《设计模式》]

  结构图



图1 decorator模式结构图

  生活中的例子

  装饰模式动态地给一个对象添加额外的职责。不论一幅画有没有画框都可以挂在墙上,但是通常都是有画框的,并且实际上是画框被挂在墙上。在挂在墙上之前,画可以被蒙上玻璃,装到框子里;这时画、玻璃和画框形成了一个物体。



图2 使用有画框的画作为例子的装饰模式对象图

  装饰模式解说

  在软件开发中,经常会遇到动态地为一个对象而不是整个类增加一些功能的问题,还是以我惯用的记录日志的例子来说明吧(也许在decorator模式里面用这个例子不是特别合适)。现在要求我们开发的记录日志的组件,除了要支持数据库记录databaselog和文本文件记录textfilelog两种方式外,我们还需要在不同的应用环境中增加一些额外的功能,比如需要记录日志信息的错误严重级别,需要记录日志信息的优先级别,还有日志信息的扩展属性等功能。在这里,如果我们不去考虑设计模式,解决问题的方法其实很简单,可以通过继承机制去实现,日志类结构图如下:



图3

  实现代码如下:

public abstract class log
{
 public abstract void write(string log);
}

public class databaselog : log
{
 public override void write(string log)
 {
  //......记录到数据库
 }
}

public class textfilelog : log
{
 public override void write(string log)
 {
  //......记录到文本文件中
 }
}

  需要记录日志信息的错误严重级别功能和记录日志信息优先级别的功能,只要在原来子类databaselog和textfilelog的基础上再生成子类即可,同时需要引进两个新的接口ierror和i priority,类结构图如下:


(点击查看原图)

图4

  实现代码如下:

public interface ierror
{
 void seterror();
}

public interface ipriority
{
 void setpriority();
}

public class dberrorlog : databaselog, ierror
{
 public override void write(string log)
 {
  base.write(log);
 }
 public void seterror()
 {
  //......功能扩展,实现了记录错误严重级别
 }
}

public class dbprioritylog : databaselog, ipriority
{
 public override void write(string log)
 {
  base.write(log);
 }
 public void setpriority()
 {
  //......功能扩展,实现了记录优先级别
 }
}

public class tferrorlog : textfilelog, ierror
{
 public override void write(string log)
 {
  base.write(log);
 }
 public void seterror()
 {
  //......功能扩展,实现了记录错误严重级别
 }
}

public class tfprioritylog : textfilelog, ipriority
{
 public override void write(string log)
 {
  base.write(log);
 }
 public void setpriority()
 {
  //......功能扩展,实现了记录优先级别
 }
}

  此时可以看到,如果需要相应的功能,直接使用这些子类就可以了。这里我们采用了类的继承方式来解决了对象功能的扩展问题,这种方式是可以达到我们预期的目的。然而,它却带来了一系列的问题。首先,前面的分析只是进行了一种功能的扩展,如果既需要记录错误严重级别,又需要记录优先级时,子类就需要进行接口的多重继承,这在某些情况下会违反类的单一职责原则,注意下图中的蓝色区域:


(点击查看原图)

图5

  实现代码:

public class dbeplog : databaselog, ierror, ipriority
{
 public override void write(string log)
 {
  seterror();
  setpriority();
  base.write(log);
 }
 public void seterror()
 {
  //......功能扩展,实现了记录错误严重级别
 }
 public void setpriority()
 {
  //......功能扩展,实现了记录优先级别
 }
}

public class tfeplog : databaselog, ierror, ipriority
{
 public override void write(string log)
 {
  seterror();
  setpriority();
  base.write(log);
 }
 public void seterror()
 {
  //......功能扩展,实现了记录错误严重级别
 }
 public void setpriority()
 {
  //......功能扩展,实现了记录优先级别
 }
}


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons