装饰模式:动态地给一个对象添加一些额外的职责。就增加功能来说,Decorator模式相比生成子类更为灵活。[GOF 《设计模式》]
这句话怎么理解?
一般来说,增加功能,一般有增加类本身的功能;另外一种是增加子类;但是现实中,靠增加子类来满足实际需求,是远远不够的,缺少灵活性;
装饰模式,它强调的要增加功能,但又不允许生产过多子类,那么该怎么实现呢? 它的指导思想,是进行包裹,层次包裹。子类对象包裹父类对象,一层一层,功能就一层一层。
1.首先定义一个首先抽象类或接口;
2.定了两个继承抽象类或实现接口方法的类,一个是装饰类,一个一般类,装饰类,定义一个方法,接受父类型;
{
装饰模式,强调的功能逐渐一层层包裹。 本例子, 以西游记中,孙悟空的72般变化,话说当年,
悟空不远千里,拜师学艺,功夫是一天天长进。腾云驾雾,翻筋斗,变美女/树等,这些功夫,是
一一学会的。
抽象虚拟类,作为父类。
所有代码 均在 Delphi7 测试通过
}
unit Decorator;
interface
uses ComObj;
type
{基础类}
TMonkey = class(TObject)
private
FMonkey: TMonkey;
public
FGongFu: string;
procedure Operation; virtual;
procedure SetGongFuMonkey(Monkey: TMonkey);
procedure WriteLog;
end;
{无法术}
TFongFuNo = class(TMonkey)
public
procedure Operation; override;
end;
{腾云驾雾}
TGongFuKey = class(TMonkey)
public
procedure Operation; override;
end;
{翻筋斗}
TGongFuSomeRsault = class(TMonkey)
public
procedure Operation; override;
end;
{变树/美人}
TGongFuChange = class(TMonkey)
public
procedure Operation; override;
procedure AddOtherMethod;
end;
implementation
uses Unit1;
{ TGongFuKey }
procedure TGongFuKey.Operation;
begin
inherited;
FGongFu := '已经学会腾云驾雾之术';
WriteLog;
end;
{ TGongGuSomeRsault }
procedure TGongFuSomeRsault.Operation;
begin
inherited;
FGongFu := '已经学会翻跟斗';
WriteLog;
end;
{ TGongFuChange }
procedure TGongFuChange.AddOtherMethod;
begin
{增加其它方法}
end;
procedure TGongFuChange.Operation;
begin
inherited;
FGongFu := '已经变美女和变树';
WriteLog;
AddOtherMethod;
{......}
end;
{ TMonkey }
procedure TMonkey.SetGongFuMonkey(Monkey: TMonkey);
begin
FMonkey := Monkey;
end;
procedure TMonkey.Operation;
begin
if FMonkey <> nil then
FMonkey.Operation;
end;
procedure TMonkey.WriteLog;
begin
Form1.Memo1.Lines.Add(FGongFu);
end;
{ TFongFuNo }
procedure TFongFuNo.Operation;
begin
inherited;
FGongFu := '无功夫,需要学习';
WriteLog;
end;
end.
{调用}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
procedure GongFun;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Decorator;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
GongFun;
end;
procedure TForm1.GongFun;
var
{猴子}
Monkey: TMonkey;
{无功夫}
FongFuNo: TFongFuNo;
{腾云驾雾}
GongFuKey: TGongFuKey;
{翻筋斗}
GongFuSomeRsault: TGongFuSomeRsault;
{变树、美女}
GongFuChange: TGongFuChange;
begin
{猴子}
Monkey := TMonkey.Create;
{无功夫}
FongFuNo := TFongFuNo.Create;
{腾云驾雾}
GongFuKey := TGongFuKey.Create;
{翻筋斗}
GongFuSomeRsault := TGongFuSomeRsault.Create;
{变树、美女}
GongFuChange := TGongFuChange.Create;
Memo1.Lines.Clear;
{注意装饰模式中,对象创建的先后顺序是可以随时可以变化的}
{情况之一 的猴子}
{
无功夫,需要学习
已经学会腾云驾雾之术
已经学会翻跟斗
已经变美女和变树
}
Form1.Memo1.Lines.Add('情况之一 的猴子: ');
FongFuNo.SetGongFuMonkey(Monkey);
GongFuKey.SetGongFuMonkey(FongFuNo);
GongFuSomeRsault.SetGongFuMonkey(GongFuKey);
GongFuChange.SetGongFuMonkey(GongFuSomeRsault);
GongFuChange.Operation;
Form1.Memo1.Lines.Add(' ');
Form1.Memo1.Lines.Add(' ');
{情况之二 的猴子}
{无功夫,需要学习
已经变美女和变树
已经学会腾云驾雾之术
已经学会翻跟斗}
Form1.Memo1.Lines.Add('情况之二 的猴子: ');
FongFuNo.SetGongFuMonkey(Monkey);
GongFuChange.SetGongFuMonkey(FongFuNo);
GongFuKey.SetGongFuMonkey(GongFuChange);
GongFuSomeRsault.SetGongFuMonkey(GongFuKey);
GongFuSomeRsault.Operation;
end;
end.
{Frm 文件}
object Form1: TForm1
Left = 297
Top = 186
Width = 312
Height = 392
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 8
Top = 312
Width = 193
Height = 25
Caption = '测试-策略模式用例'
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 8
Top = 8
Width = 249
Height = 297
Lines.Strings = (
'Memo1')
TabOrder = 1
end
end