• 装饰者模式


    一.模式解说

    以客户端透明的方式动态地将责任附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案。装饰者模式用意是要保持对象接口,增强对象性能.

    实际生活中经常发现装饰者模式.比如,你需要装裱挂画,你不想讲画和画框定死以便更换不同的画框.下图就是一个装裱挂画的装饰者模式.

    装饰者模式的使用时机:

    1. 在不影响其他对象的情况下,动态透明的增加责任到一个对象.

    2.希望责任和功能可以随时增加或取消.

    3.当无法通过类继承来扩展功能时.

    二.结构和用法

    2.1 模式结构

     装饰者模式结构如下图:

    包含以下参与者:

    1. 抽象部件(TComonent):定义一个接口可以动态的附加责任到其他对象.

    2.具体部件(TConcreteComponent): 定义可以被附加责任的对象.

    3.装饰者(TDecorator): 维护一个抽象部件对象的引用,并定义与抽象部件接口一致的接口,以便装饰抽象部件对象接口.

    4.具体装饰者(TConcreteDecorator): 附加责任到抽象部件,完成具体的装饰.

    2.2 代码模板(Delphi)

       

    unit Decorator;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs;
    
    type
      Tcomponent = class(TObject)
      public
        procedure Operation; virtual; abstract;
      end;
    
      TConcreteComponent = class(Tcomponent)
      public
        procedure Operation; override;
      end;
    
      TDecorator = class(Tcomponent)
      private
        FComponent: TComponent;
      public
        constructor Create(Component: TComponent);
        procedure Operation;overload; override;
      end;
    
      TConcreteDecoratorA = class(TDecorator)
      private
        FAddedState: integer;
      public
        procedure Operation;override;
      end;
    
      TConcreteDecoratorB = class(TDecorator)
      public
        procedure AddedBehavior;
        procedure Operation;override;
      end;
    
    implementation
    
    { TConcreteComponent }
    
    procedure TConcreteComponent.Operation;
    begin
      //被装饰者部件的操作代码
    end;
    
    { TDecorator }
    
    constructor TDecorator.Create(Component: TComponent);
    begin
      FComponent := Component;
    end;
    
    procedure TDecorator.Operation;
    begin
      if FComponent <> nil then
        FComponent.Operation;
    end;
    
    { TConcreteDecoratorA }
    
    procedure TConcreteDecoratorA.Operation;
    begin
      //装饰部件操作代码
    end;
    
    { TConcreteDecoratorB }
    
    procedure TConcreteDecoratorB.AddedBehavior;
    begin
      //装饰者新增操作的代码
    end;
    
    procedure TConcreteDecoratorB.Operation;
    begin
      //装饰部件操作代码
      // 注意这里是装饰后已经扩展了对象的功能
      inherited Operation;
      AddedBehavior;
    end;
    
    end.

     2.3 问题讨论

     三. 范例与实践

    3.1 装饰者模式在图片观赏器中的应用

     

     部分示例代码:

    unit PicDecorator;
    
    interface
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, ExtCtrls, ComCtrls, Jpeg;
    
    type
    
      TPicShow = class(TObject)
      public
        procedure Display(Owner: TForm; ImgFile: string); virtual; abstract;
      end;
    
      TPic = class(TPicShow)
      public
        procedure Display(Owner: TForm; ImgFile: string); override;
      end;
    
      TDecoratedPic = class(TPicShow)
      private
        FComponent: TPicShow;
      public
        constructor Create(PicShow: TPicShow);
        procedure Display(Owner: TForm; ImgFile: string); overload; override;
      end;
    
      TPicWithFrame = class(TDecoratedPic)
      private
        FAddedFrame: integer;
      public
        procedure Display(Owner: TForm; ImgFile: string); override;
        destructor Destroy; override;
      end;
    
      TPicWithMusic = class(TDecoratedPic)
      public
        destructor Destroy; override;
        procedure AddMusic;
        procedure Display(Owner: TForm; ImgFile: string); override;
      end;
    
    implementation
    
    { TPic }
    
    procedure TPic.Display(Owner: TForm; ImgFile: string);
    var
      Img : TImage;
    begin
      Img := TImage.Create(Owner);
      Img.Picture.LoadFromFile(ImgFile);
      Img.AutoSize := True;
      Img.Stretch := True;
      Owner.Width := Img.Width + 32;
      Owner.Height := Img.Height + 64;
      Owner.Caption := ImgFile;
      Img.Left := 11;
      Img.Top := 13;
      Img.Parent := Owner;
    end;
    
    { TDecoratedPic }
    
    constructor TDecoratedPic.Create(PicShow: TPicShow);
    begin
      Self.FComponent := PicShow;
    end;
    
    procedure TDecoratedPic.Display(Owner: TForm; ImgFile: string);
    begin
      if FComponent <> nil then
        FComponent.Display(Owner, ImgFile);
    end;
    
    { TPicWithFrame }
    
    destructor TPicWithFrame.Destroy;
    begin
      if FComponent <> nil then FComponent.Free;
    end;
    
    procedure TPicWithFrame.Display(Owner: TForm; ImgFile: string);
    var
      FrmOut: TBevel;
      FrmIn: TBevel;
    begin
      inherited Display(Owner, ImgFile);
      FrmIn := Tbevel.Create(Owner);
      FrmIn.Parent := Owner;
      FrmIn.Width := Owner.Width - 30;
      FrmIn.Height := Owner.Height - 62;
      FrmIn.Left := 10;
      FrmIn.Top := 12;
      FrmIn.Shape := bsBox;
      FrmIn.Style := bsLowered;
    
      FrmOut := Tbevel.Create(Owner);
      FrmOut.Parent := Owner;
      FrmOut.Width := Owner.Width - 18;
      FrmOut.Height := Owner.Height - 48;
      FrmOut.Left := 4;
      FrmOut.Top := 6;
      FrmOut.Shape := bsBox;
      FrmOut.Style := bsRaised;
    end;
    
    { TPicWithMusic }
    
    procedure TPicWithMusic.AddMusic;
    begin
      SndPlaySound('SONG.wav', SND_ASYNC or SND_NODEFAULT);
    end;
    
    destructor TPicWithMusic.Destroy;
    begin
      if Self.FComponent <> nil then Self.FComponent.Free;
    end;
    
    procedure TPicWithMusic.Display(Owner: TForm; ImgFile: string);
    begin
      inherited Display(Owner, ImgFile);
      AddMusic;
    end;
    
    end.

    四.总结

  • 相关阅读:
    Java单例模式(Singleton)以及实现
    golang 垃圾回收机制
    MySQL索引背后的数据结构及算法原理
    简述拥塞控制的四种基本算法
    分库分表
    lvalue & rvalue
    理解linux cpu load
    android使用百度地图SDK获取定位信息
    iOSUIWebView---快停下啦,你的愚蠢的行为
    【翻译自mos文章】当/var/tmp文件夹被remove掉之后,GI crash,并启动失败,原因是ohasd can not create named pipe
  • 原文地址:https://www.cnblogs.com/lp-blogs/p/6014581.html
Copyright © 2020-2023  润新知