以客戶端透明的方式動態地將責任附加到對象上.若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。裝飾者模式用意是要保持對象接口,加強對象性能.ide
實際生活中常常發現裝飾者模式.好比,你須要裝裱掛畫,你不想講畫和畫框定死以便更換不一樣的畫框.下圖就是一個裝裱掛畫的裝飾者模式.性能
裝飾者模式的使用時機:spa
1. 在不影響其餘對象的狀況下,動態透明的增長責任到一個對象.3d
2.但願責任和功能能夠隨時增長或取消.code
3.當沒法經過類繼承來擴展功能時.component
裝飾者模式結構以下圖:orm
包含如下參與者:對象
1. 抽象部件(TComonent):定義一個接口能夠動態的附加責任到其餘對象.blog
2.具體部件(TConcreteComponent): 定義能夠被附加責任的對象.繼承
3.裝飾者(TDecorator): 維護一個抽象部件對象的引用,並定義與抽象部件接口一致的接口,以便裝飾抽象部件對象接口.
4.具體裝飾者(TConcreteDecorator): 附加責任到抽象部件,完成具體的裝飾.
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.
部分示例代碼:
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.