`
cooldesigner
  • 浏览: 68536 次
  • 性别: Icon_minigender_1
最近访客 更多访客>>
社区版块
存档分类
最新评论

Decorator

阅读更多

起源<o:p></o:p>

DelphiDecorator模式是在Decorator的基础上进行了扩展。更多Decorator模式的资料请参阅 《设计模式115页》<o:p></o:p>

目的<o:p></o:p>

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

动机<o:p></o:p>

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

<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></v:path><o:lock v:ext="edit" aspectratio="t"></o:lock></v:shapetype>

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

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

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

一个灵活的方法是将文本流嵌入另一个对象中,由这个对象加入缓存器不规则化。我们称这个嵌入的对象为装饰(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。其后代如TindentFilterTupperCaseFilter通过简单重载装饰类的方法加入了一些新职责。<o:p></o:p>

 

 

 

 

 

 

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

 

 

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

 

应用

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

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;

 <o:p></o:p>

  TTextFilter = class (TTextStream)

  private

    FOwnsStream: Boolean;

    FTextStream: TTextStream;

  protected

    function GetEndOfText: Boolean; override;

    function GetTextStream: TTextStream;

    procedure SetTextStream(Value: TTextStream);

  public

    constructor Create(ATextStream: TTextStream; AOwnsStream: Boolean);

    destructor Destroy; override;

    function ReadLine: string; override;

    procedure WriteLine(const Line: string); override;

    property OwnsStream: Boolean read FOwnsStream write FOwnsStream;

    property TextStream: TTextStream read GetTextStream write SetTextStream;

  end;

 <o:p></o:p>

代码说明:

·      属性TextStream包含了对装饰的文本流对象的引用。TextStream具有读、写的操作。这样对后代来说就更灵活了。一个类似的模式的proxy模式,通过读、写方法在proxy模式也是一种好的应用。有关proxy模式请参考《设计模式》。

·      属性OwnsStream用来TextStream的所有权。在下面的实现代码中你可以看到TtextFilter类在free它所有的文本流时先判断OwnsStream是否为真。它取到帮助装饰清除的作用。

·      TextStreamOwnsStream装饰类的构造器的两个参数。

·      实现装饰类重载了ReadLineWriteLineGetEndOfText三个方法。并加入了实现。

下面是它的实现部分代码:

 <o:p></o:p>

constructor TTextFilter.Create(ATextStream: TTextStream; AOwnsStream: Boolean);

begin

  inherited Create;

  TextStream := ATextStream;

  OwnsStream := AOwnsStream;

end;

 <o:p></o:p>

destructor TTextFilter.Destroy;

begin

  TextStream := nil;

  inherited Destroy;

end;

 <o:p></o:p>

function TTextFilter.GetEndOfText: Boolean;

begin

  Result := TextStream.GetEndOfText;

end;

 <o:p></o:p>

function TTextFilter.GetTextStream: TTextStream;

begin

  Result := FTextStream;

end;

 <o:p></o:p>

function TTextFilter.ReadLine: string;

begin

  Result := TextStream.ReadLine;

end;

 <o:p></o:p>

procedure TTextFilter.SetTextStream(Value: TTextStream);

begin

  if Value <> FTextStream then

  begin

    if OwnsTextStream then FTextStream.Free;

    FTextStream := Value;

  end;

end;

 <o:p></o:p>

procedure TTextFilter.WriteLine(const Line: string);

begin

  TextStream.WriteLine(Line);

end;

在这些实现代码一个非常有兴趣的是:

·      装饰类的行为方法ReadLineWriteLineGetEndOfText只是简单的调用相应的TextStream方法。

·      SetTextStream方法在分配一个新的值前安全的释放它的方本流。

·      释造函数将TextStream := nil,因为在SetTextStream有可能释放当前的文本流。

现在可能真正的创建一个将文本转换成大写的过滤器了

接口部分的代码:

type

  TUpperCaseFilter = class (TTextFilter)

  public

»   function ReadLine: string; override;

»   procedure WriteLine(const Line: string); override;

  end;

 <o:p></o:p>

implementation

 <o:p></o:p>

function TUpperCaseFilter.ReadLine: string;

begin

» Result := UpperCase(inherited ReadLine);

end;

 <o:p></o:p>

procedure TUpperCaseFilter.WriteLine(const Line: string);

begin

» inherited WriteLine(UpperCase(Line));

end;

这个装饰类可以被子任何TtextStream目标使用:

 <o:p></o:p>

function TClient.CreateOutput: TTextStream;

begin

» { 创建一个基类}

» case Destination of

»   dsFile: Result := TTextFile.Create(GetFileName, fmCreate);

»   dsPrinter: Result := TLinePrinter.Create;

» end;

» {判断是是否使用了装饰, 并使用同样的参数

»   重要的是我们没必要关心是装饰TTextFile ,还是TLinePrinter }

» if ConvertToUpperCase then

»   Result := TUpperCaseFilter.Create(Result, True);

end;

 <o:p></o:p>

procedure TClient.ListContents;

var

  T: TTextStream;

begin

  T := CreateOutput;

  {

分享到:
评论

相关推荐

    decorator-4.1.2.rar ,亲测可用

    《Python装饰器深入解析——基于decorator-4.1.2版本》 在Python编程语言中,装饰器(Decorator)是一种强大的工具,它允许我们修改或增强函数、类或其他可调用对象的行为,而无需改动它们的源代码。在本文中,我们...

    decorator-4.1.2.tar.gz

    装饰器(Decorator)在Python编程语言中是一种强大的设计模式,它允许我们动态地修改或增强函数、类或对象的行为。`decorator-4.1.2.tar.gz` 是一个特定版本(4.1.2)的装饰器库的归档文件,这个库专门用于支持...

    WPF 装饰器Decorator 和 Adorner综合实例

    在Windows Presentation Foundation (WPF) 中,装饰器(Decorator)和adorner是两种非常重要的UI元素,它们可以用于增强和扩展WPF控件的功能和视觉表现。本文将深入探讨这两种技术,并通过具体实例来阐述其在实际开发...

    设计模式之 Decorator模式和代码实现

    【Decorator模式】是一种设计模式,它允许在运行时动态地给对象添加新的责任或功能,而不必通过子类化的方式。在上述的奇幻RPG游戏中,Decorator模式被用来实现武器的锻造过程,尤其是武器镶嵌宝石的功能。这个过程...

    java Decorator装饰模式例子

    装饰模式(Decorator Pattern)是设计模式中的一种结构型模式,它允许在运行时给对象添加新的行为或职责,而无需改变对象的类。在Java中,装饰模式通常通过继承和组合来实现,使得代码具有更好的扩展性和灵活性。...

    vue脚手架,vue3 组件 vue-property-decorator 组件

    `vue-property-decorator`是一个库,它是Vue.js和TypeScript的结合,提供了装饰器来帮助我们在TypeScript中更好地声明和管理组件的属性。它使得我们可以利用TypeScript的强类型系统,提高代码的可维护性和可读性。...

    decorator python(decorator-3.4.0.tar.gz).rar

    这个"decorator python"模块是版本3.4.0的实现,其核心概念是通过函数来包装(即装饰)其他函数,以增强被装饰函数的行为。这个模块可能是由社区成员贡献并分享的,因此它属于"其他资源"类别。 在Python中,装饰器...

    PyPI 官网下载 | protocol_implements_decorator-0.3.1.tar.gz

    标题中的"PyPI 官网下载 | protocol_implements_decorator-0.3.1.tar.gz"表明这是一个在Python Package Index(PyPI)上发布的软件包,名为`protocol_implements_decorator`,版本为0.3.1,且以tar.gz格式打包。...

    mybatis3+springmvc4+angularjs+mysql+decorator实例

    这是一个整合了多个技术框架的项目实例,主要涵盖了MyBatis3、SpringMVC4、AngularJS、MySQL数据库以及Decorator模式的应用。以下是对这些技术及其在项目中的应用进行的详细解释: 1. MyBatis3:MyBatis是一个优秀...

    设计模式之装饰模式(Decorator Pattern)

    装饰模式(Decorator Pattern)是一种结构型设计模式,它在不改变原有对象的基础上,通过包裹一个对象并为其添加新的行为或责任,实现对对象功能的扩展。这种模式在软件开发中非常常见,尤其当需要在运行时动态改变...

    装饰器模式[Decorator]

    装饰器模式(Decorator)是一种设计模式,它允许在运行时向对象添加新的行为或责任,而无需修改对象的源代码。这种模式属于结构型模式,是面向对象设计中的一种非常实用的技术。 装饰器模式的核心思想是通过将一个...

    前端开源库-pure-render-decorator

    `pure-render-decorator`是一个非常有用的开源库,它专门设计用于提升React组件的性能,通过确保只在必要时进行渲染,从而降低不必要的DOM操作。这个库的核心理念是实现“纯渲染”,也就是当组件的props或state没有...

    Decorator-3.4.0

    "Decorator-3.4.0" 是一个Python装饰器库的版本,提供了方便和灵活的方式来创建装饰器。这个版本的压缩包文件名为"decorator-3.4.0.tar.gz",它是一个常见的归档格式,用于存储和分发源代码。 在Python中,装饰器...

    C++ Decorator模式

    Decorator模式是设计模式中的一种结构型模式,它允许在运行时动态地给对象添加新的行为或职责,而不会破坏封装性。这种模式的核心思想是通过装饰类包装原对象,实现对原对象功能的扩展,同时保持与原接口的一致性。 ...

    [结构型模式] head first 设计模式之装饰者模式(decorator)

    【标题】:“装饰者模式(decorator)在Head First设计模式中的详解” 【内容】: 装饰者模式(Decorator Pattern)是结构型设计模式之一,它允许动态地给一个对象添加新的功能,而无需修改其原有代码。这个模式的...

    timeout_decorator.py

    windows系统下的python超时装饰器,解决pypi中timeout-decorator库在windows系统上不可用的问题。

    decorator-4.2.1-py2.py3-none-any.whl

    decorator-4.2.1-py2.py3-none-any.whl

    decorator-wechat,微信现代化(Nevolution decorator).zip

    decorator-wechat,微信现代化(Nevolution decorator).zip

    PyPI 官网下载 | decorator-4.0.11-py2.py3-none-any.whl

    资源来自pypi官网。 资源全名:decorator-4.0.11-py2.py3-none-any.whl

    sequelize-typescript, decorator和sequelize的一些其他特性( + v4 ).zip

    sequelize-typescript, decorator和sequelize的一些其他特性( + v4 ) sequelize装饰器和 sequelize ( v3,v4,v5 )的一些其他特性。模型定义@Table API@Column API使用情况配置文件模型路径解析模型关联插件On

Global site tag (gtag.js) - Google Analytics