策略模式(Strategy Pattern).
定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。Strategy模式将逻辑(算法)封装到一个类里面,通过组合的方式将具体算法的实现在组合对象中实现,通过委托的方式将抽象接口的实现委托给组合对象实现。
1.设计原则:
a.找出应用中的可能变化之处,把它们独立出来,不要和那些不需要变化的代码混起来。(系统的某部分的改变不会影响其他部分)。
b.针对接口编程(利用多态针对超类型(通常为抽象类)进行编程),而不是针对实现编程。把会变化的行为抽取出来变成单独的接口,构成行为类。
c.多用组合,少用继承.(鸭子的行为不是继承过来的而是通过行为对象组合过来的)
2继承和组合的优缺点:
继承:
a.优点:易于修改和扩展那些被复用的实现
b.缺点:1)破坏了封装性,继承中父类的实现细节暴露给子类了;
2)“白盒”复用,原因在1)中;
3)当父类的实现更改时,其所有子类将不得不随之改变
4)从父类继承而来的实现在运行期间不能改变(编译期间就已经确定了)。
组合
a.优点:
1)“黑盒”复用,因为被包含对象的内部细节对外是不可见的;2)封装性好,原因为1);
3)实现和抽象的依赖性很小(组合对象和被组合对象之间的依赖性小);
4)可以在运行期间动态定义实现(通过一个指向相同类型的指针,典型的是抽象
基类的指针)。
b.缺点:系统中对象过多。 从上面对比中我们可以看出,组合相比继承可以取得更好的效果,因此在面向对象的设计中的有一条很重要的原则就是:优先使用(对象)组合,而非(类)继承(Favor CompositionOver Inheritance)。
下面用C++实现《Head First设计模式》书中的鸭子模拟器的策略模式,类的关系图如下:
头文件Duck.h
#ifndef _DUCK_H_ #define _DUCK_H_ #include "Behavior.h" class Duck { public: Duck(); ~Duck(); void swim(); //所有的子类共有的行为 virtual void display();//子类必须覆盖 void performQuack(); void performFly(); void setFlyBehavior(FlyBehavior *flyBehavior); void setQuackBehavior(QuackBehavior *quackBehavior); protected: FlyBehavior *flyBehavior; QuackBehavior *quackBehavior; }; class MallardDuck:public Duck { public: MallardDuck(); virtual ~MallardDuck(); void display(); protected: private: }; #endif //_DUCK_H_
源文件Duck.CPP
#include "Duck.h" #include <iostream> using namespace std; Duck::Duck() { } Duck::~Duck() { if(!flyBehavior) delete flyBehavior; if(!quackBehavior) delete quackBehavior; cout<<"~Duck()....."<<endl; } void Duck::swim() { cout<<"All ducks float,even decoys...."<<endl; } void Duck::display() { cout<<"Duck::display()"<<endl; } void Duck::performFly() { flyBehavior->fly(); } void Duck::performQuack() { quackBehavior->quack(); } MallardDuck::MallardDuck() { quackBehavior=new Quack(); flyBehavior=new FlyWithWings(); } MallardDuck::~MallardDuck() { cout<<"~MallardDuck()...."<<endl; } void MallardDuck::display() { cout<<"I am a Mallard duck...."<<endl; } void Duck::setFlyBehavior(FlyBehavior *flyBehavior) { this->flyBehavior=flyBehavior; } void Duck::setQuackBehavior(QuackBehavior *quackBehavior) { this->quackBehavior=quackBehavior; }
头文件Behavior.h
#ifndef _BEHAVIOR_H_ #define _BEHAVIOR_H_ //抽象基类 class FlyBehavior { public: FlyBehavior(); virtual ~FlyBehavior(); virtual void fly()=0; }; class QuackBehavior { public: virtual void quack()=0; }; //鸭子飞的行为 class FlyWithWings:public FlyBehavior { public: FlyWithWings(); virtual ~FlyWithWings(); void fly(); }; class FlyNoWay:public FlyBehavior { public: void fly(); }; //鸭子叫的行为 class Quack:public QuackBehavior { public: void quack(); }; class MuteQuack:public QuackBehavior { public: void quack(); }; #endif
源文件Behavior.CPP
#include "Behavior.h" #include <iostream> using namespace std; FlyBehavior::FlyBehavior() { } FlyBehavior::~FlyBehavior() { cout<<"~FlyBehavior()"<<endl; } FlyWithWings::FlyWithWings() { } FlyWithWings::~FlyWithWings() { cout<<"~~FlyWithWings()"<<endl; } void FlyWithWings::fly() { cout<<"I am flying..."<<endl; } void FlyNoWay::fly() { cout<<"I can't fly..."<<endl; } void Quack::quack() { cout<<"I am Quack"<<endl; } void MuteQuack::quack() { cout<<"I am MuteQuack..."<<endl; }
主函数main.CPP代码
#include "Duck.h" #include "Behavior.h" #include <iostream> using namespace std; int main(int argc,char* argv[]) { Duck * mallard=new MallardDuck(); //mallard->setFlyBehavior(new FlyWithWings()); mallard->display(); mallard->swim(); mallard->performFly(); mallard->performQuack(); mallard->setFlyBehavior(new FlyNoWay()); mallard->performFly(); if (NULL != mallard) delete mallard; return 0; }
运行结果如下: