2018-12-03 策略模式
策略模式:定义了算法族,分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
用接口实现多态,但是却不能复用代码,要解决这个问题,就要用类来实现多态和代码复用
把变化的部份提取出来,设计成接口
//飞行的接口
IFlyBehavior=interface
procedure fly;
end;
//实现飞行的类
TFlyWithWings=class(TInterfacedObject,IFlyBehavior)
procedure fly;
end;
//实现不能飞行的类
TFlyNoWay=class(TInterfacedObject,IFlyBehavior)
procedure fly;
end;
//叫的接口
IQuackBehavior=interface
procedure quack;
end;
//实现呱呱叫的接口
TQuack=class(TInterfacedObject,IQuackBehavior)
procedure quack;
end;
//实现不能叫的接口
TMuteQuack=class(TInterfacedObject,IQuackBehavior)
procedure quack;
end;
//实现吱吱叫的接口
TSqueak=class(TInterfacedObject,IQuackBehavior)
procedure quack;
end;
//鸭子的基类设计
TDuck=class
private
//叫的接口
FquackBehavior: IQuackBehavior;
//飞行的接口
FflyBehavior: IFlyBehavior;
procedure SetflyBehavior(const Value: IFlyBehavior);
procedure SetquackBehavior(const Value: IQuackBehavior);
public
property flyBehavior:IFlyBehavior read FflyBehavior write SetflyBehavior;
property quackBehavior:IQuackBehavior read FquackBehavior write SetquackBehavior;
procedure display; virtual; //虚拟方法,由子类具体实现
procedure swim;//子类通用方法,由基类实现
procedure performFly;//实现子类多态的飞行方法
procedure performQuack;//实现子类多态的叫方法
end;
//绿头鸭的类设计
TMallardDuck=class(TDuck)
public
constructor create;
procedure display;
end;
//类的具体实现
{ TFlyWithWings }
procedure TFlyWithWings.fly;
begin
showmessage('我在飞行');
end;
{ TFlyNoWay }
procedure TFlyNoWay.fly;
begin
showmessage('我不会飞行');
end;
{ TQuack }
procedure TQuack.quack;
begin
showmessage('呱呱');
end;
{ TMuteQuack }
procedure TMuteQuack.quack;
begin
showmessage('我不会叫');
end;
{ TSqueak }
procedure TSqueak.quack;
begin
showmessage('吱吱');
end;
{ TDuck }
procedure TDuck.display;
begin
end;
procedure TDuck.performFly;
begin
FflyBehavior.fly;
end;
procedure TDuck.performQuack;
begin
FquackBehavior.quack;
end;
procedure TDuck.SetflyBehavior(const Value: IFlyBehavior);
begin
FflyBehavior := Value;
end;
procedure TDuck.SetquackBehavior(const Value: IQuackBehavior);
begin
FquackBehavior := Value;
end;
procedure TDuck.swim;
begin
showmessage('我在游泳');
end;
{ TMallardDuck }
constructor TMallardDuck.create;
begin
//把接口绑定到具体的对象上
FflyBehavior := TFlyWithWings.Create;
FquackBehavior := TQuack.Create;
end;
procedure TMallardDuck.display;
begin
showmessage('我是绿头鸭');
end;
//调用对象
var
MallardDuck:TMallardDuck;
begin
MallardDuck:=TMallardDuck.create;
MallardDuck.display;
MallardDuck.swim;
MallardDuck.performFly;
MallardDuck.performQuack;
end;
把需要重用的代码,放在实现接口的类中,就可以同时兼顾多态和代码重用
可以动态指定行为对象,来实现方法的多态
例如:新增一个火箭动力飞行的行为类
TFlyRocketPower=class(TInterfacedObject,IFlyBehavior)
procedure fly;
end;
类的具体实现
{ TFlyRocketPower }
procedure TFlyRocketPower.fly;
begin
showmessage('使用火箭动力飞行');
end;
动态指定行为类
var
MallardDuck:TMallardDuck;
FlyRocketPower:TFlyRocketPower;
begin
MallardDuck:=TMallardDuck.create;
FlyRocketPower:=TFlyRocketPower.Create;
MallardDuck.flyBehavior:= FlyRocketPower;
MallardDuck.display;
MallardDuck.swim;
MallardDuck.performFly;
MallardDuck.performQuack;
end;