策略模式(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;
}
运行结果如下: