技术开发 频道

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

  到这里,LogErrorWrapper类和LogPriorityWrapper类真正实现了对错误严重级别和优先级别的功能的扩展。我们来看一下客户程序如何去调用它:

public class Program {  public static void Main(string[] args)  {   Log log = new DatabaseLog();   LogWrapper lew1 = new LogErrorWrapper(log);   //扩展了记录错误严重级别   lew1.Write( "Log Message");   LogPriorityWrapper lpw1 = new LogPriorityWrapper(log);   //扩展了记录优先级别   lpw1.Write( "Log Message");   LogWrapper lew2 = new LogErrorWrapper(log);   LogPriorityWrapper lpw2 = new LogPriorityWrapper(lew2); //这里是lew2   //同时扩展了错误严重级别和优先级别   lpw2.Write( "Log Message");  } }
  注意在上面程序中的第三段装饰才真正体现出了Decorator模式的精妙所在,这里总共包装了两次:第一次对log对象进行错误严重级别的装饰,变成了lew2对象,第二次再对lew2对象进行装饰,于是变成了lpw2对象,此时的lpw2对象同时扩展了错误严重级别和优先级别的功能。也就是说我们需要哪些功能,就可以这样继续包装下去。到这里也许有人会说LogPriorityWrapper 类的构造函数接收的是一个Log对象,为什么这里可以传入LogErrorWrapper对象呢?通过类结构图就能发现,LogErrorWrapper类其实也是Log类的一个子类。
 
  我们分析一下这样会带来什么好处?首先对于扩展功能已经实现了真正的动态增加,只在需要某种功能的时候才进行包装;其次,如果再出现一种新的扩展功能,只需要增加一个对应的包装子类(注意:这一点任何时候都是避免不了的),而无需再进行很多子类的继承,不会出现子类的膨胀,同时Decorator模式也很好的符合了面向对象设计原则中的优先使用对象组合而非继承开放-封闭原则。
 
  .NET中Decorator模式一个典型的运用就是关于Stream,BufferedStream和CryptoStream其实就是两个包装类,这里的Decorator模式省略了抽象装饰角色(Decorator),示例代码如下:
class Program {  public static void Main(string[] args)  {  MemoryStream ms =new MemoryStream(new byte[]{100,456,864,222,567});  //扩展了缓冲的功能  BufferedStream buff = new BufferedStream(ms);  //扩展了缓冲,加密的功能  CryptoStream crypto = new CryptoStream(buff);  } }
  通过反编译,可以看到BufferedStream类的代码(只列出部分),它是继承于Stream类:
public sealed class BufferedStream : Stream {  // Methods  private BufferedStream();  public BufferedStream(Stream stream);  public BufferedStream(Stream stream, int bufferSize);  // Fields  private int _bufferSize;  private Stream _s; }
  效果及实现要点
 
  1.Component类在Decorator模式中充当抽象接口的角色,不应该去实现具体的行为。而且Decorator类对于Component类应该透明,换言之Component类无需知道Decorator类,Decorator类是从外部来扩展Component类的功能。
 
  2.Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。我们可以使用一个或者多个Decorator对象来装饰一个Component对象,且装饰后的对象仍然是一个Component对象。
 
  3.Decortor模式并非解决多子类衍生的多继承问题,Decorator模式的应用要点在于解决主体类在多个方向上的扩展功能”——是为装饰的含义。
 
  4.对于Decorator模式在实际中的运用可以很灵活。 如果只有一个ConcreteComponent类而没有抽象的Component类,那么Decorator类可以是ConcreteComponent的一个子类。
 
  如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator的责任合并成一个类。
 
  5.Decorator模式的优点是提供了比继承更加灵活的扩展,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合。
 
  6.由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。
 
  适用性
 
  在以下情况下应当使用装饰模式:
 
  1.需要扩展一个类的功能,或给一个类增加附加责任。
 
  2.需要动态地给一个对象增加功能,这些功能可以再动态地撤销。
 
  3.需要增加由一些基本功能的排列组合而产生的非常大量的功能,从而使继承关系变得不现实。
 
  总结
 
  Decorator模式采用对象组合而非继承的手法,实现了在运行时动态的扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了单独使用继承带来的灵活性差多子类衍生问题。同时它很好地符合面向对象设计原则中优先使用对象组合而非继承开放-封闭原则。

 

 

 

0
相关文章