打印本文 打印本文 关闭窗口 关闭窗口
设计模式、用Delphi实现----Decorator 模式
作者:武汉SEO闵涛  文章来源:敏韬网  点击数1678  更新时间:2009/4/23 18:40:58  文章录入:mintao  责任编辑:mintao

 

 

 

Decorator 模式

起源

Delphi的Decorator模式是在Decorator的基础上进行了扩展。更多Decorator模式的资料请参阅 《设计模式115页》

目的

动态地给一个对象添加一些职责。就增加功能来说,Decorator模式比增加子类更为灵活.

动机

我们经常要为某一些个别的对象增加一些新的职责,并不是全部的类。假设,我们有一组类用来输出文本行。抽象类TtextStream定义了一些接口,而后代如TtextFile、TlinePrinter、TclipboardStream则实现了这些接口。

现在,假设我们想给这些类增加一些新的职责如:文本缓存器、大小定转换、文本分析。

继承机制是添加功能的一种有效途径。从TtextStream类继承了缓存器可以被多个子类的实例使用。但不是很灵活。因为缓存器的选择是静态的了。客户程序不能控制选择缓存器的方式和时机。如此,加重了抽象类TtextStream的字段的负担来控制缓存器,并将带入到它的第一个实例中。通常最好保持高层次的(抽象)基类的轻量。在基类中增加不规则化和原文分析会使它最变得非常笨重!

如果你不想创建一个重量级的基类就会产生别外一个问题。有这样一种情况:大量的独立的继承是可能是,但瀑发式的产生大量的子类来支持不同组合如:TbufTextFile、TscrambledTextFile、TbufScrambledTextFile、TbufLinePrinter、TscrambledLinePrinter及其它。发生同样问题,如果类定义对子类隐藏或不可见的。比如说,如果你想在第三的组件库的高层类中加入一个新的职责,试着给Delphi的Tstream加入一个新的职责!

一个灵活的方法是将文本流嵌入另一个对象中,由这个对象加入缓存器或不规则化。我们称这个嵌入的对象为装饰(Decorator)。这个装饰与文本流组件接口一致,因些它对使用文本流客户程序是透明的。在Delphi中保持接口一致意味着从一个共公的组先继承,例中为TtextStream。装饰将请求向前转到到文本流,并且可能能转发前后执行一些额外的动作(如缓存器、不规则化),透明性使你可以递归的嵌套多个装饰,从面可以添加任意多的功能。

假设类TtextStream的接口如下:

type

  TTextStream = class (TObject)

  protected

    function GetEndOfText: Boolean; virtual; abstract;

  public

    function ReadLine: string; virtual; abstract;

    procedure WriteLine(const Line: string); virtual; abstract;

    property EndOfText: Boolean read GetEndOfText;

  end;

使用adapter可以创建一些真实的文本流组件,如TLinePrinter, TtextFile,其它更多的。为了保持接口的一致。使用decorator模式,我们可以灵活的为所有的文本流加入新功能。假设我们将装饰类命名为TtextFilter。这个类从TtextStream继承过来从而保TTextStream证接口的兼容,它同样包含了对TtextStream实例TextStream的引用。类TtextFilter没有实现任何新特性,它只是简单的将所有客户程序的请求(方法调用)转发给类TextStream。其后代如:TindentFilter、TupperCaseFilter通过简单重载装饰类的方法加入了一些新职责。

 

 

 

 

 

 

下面的流程图显示了TupperCaseFilter是如何调解客户程序对类TtextStream调用

 

 

此模式最重要的是让装饰类显示TtextStream能显示的任何部份。这样通常客户对调用装饰类和末装饰的类没有什么不同, 后它们对装饰类不存在任何依赖关系。在本单元的例子中,客户程序不知道它的文本在实际的写操作之前被转换成大写。

 

应用

下面的代码演示了类的装饰模式的应用。例子中的TtextStream为装饰类TtextFilter定义了一个抽象的接口。

type

  TTextStream = class (TObject)

  protected

    function GetEndOfText: Boolean; virtual; abstract;

  public

    function ReadLine: string; virtual; abstract;

    procedure WriteLine(const Line: string); virtual; abstract;

    property EndOfText: Boolean read GetEndOfText;

  end;

 

  TTextFilter = class (TTextStream)

  private

    FOwnsStream: Boolean;

    FTextStream: TTextStream;

  protected

    function GetEndOfText: Boolean; override;

[1] [2] [3]  下一页

打印本文 打印本文 关闭窗口 关闭窗口