[设计模式]行为模式-策略模式(C++描述)
second60 20180507
1. 什么是策略模式
回顾下上节,模板方法是把业务逻辑的具体实现和抽象接口之间解耦,是通过子类继承父类的方法来实现,并把算法的流程封装到抽象类中。所以这样就导致了模板方法继承的强约束性,即如查新加一个流程,必须修改抽象接口,同时在子类中添加实现方法。改动非常大。
策略模式,是采用组合的方式实现了模板方法的功能,即具体实现和抽象接口解耦,但流程方法并不是在抽象父中,而是在另一个Context中来实现流程.
2. 策略模式结构图
抽象策略类:Strategy,抽象出所有子类要实现的算法接口
具体策略类:具体的算法实现,不同算法实现继承抽象策略类实现相关功能
环境角色:Context 具体的算法流程
与模版方法的区别:就是算法流程抽离到Context中,用组合的方法而非继承的方式实现。
代码:
// 策略抽象类
class Strategy
{
public:
virtual ~Strategy(){};
virtual void algrithm1() = 0;
virtual void algrithm2() = 0;
virtual void algrithm3() = 0;
};
// 具体实现类1
class ConcreteStrategyA:public Strategy
{
public:
void algrithm1(){//do1}
void algrithm2(){//do2}
void algrithm3(){//do3}
};
// 具体实现类2
class ConcreteStrategyB:public Strategy
{
public:
void algrithm1(){//do11}
void algrithm2(){//do22}
void algrithm3(){//do33}
};
// 环境角色类
class Context
{
public:
Context(Strategy *strategy){_strategy = strategy;}
~Context(){}
// 算法流程1
void doAction()
{
_strategy->algrithm1();
_strategy->algrithm2();
_strategy->algrithm3();
}
// 算法流程2
void doAction2()
{
_strategy->algrithm1();
_strategy->algrithm3();
}
private:
Strategy *_strategy;
};
// 使用
int main()
{
//使用算法1来实现某算法
Strategy *strategy1 = new ConcreteStrategyA();
Context* context = new Context(strategy1);
context->doAction();
context->doAction2();
//使用算法2来实现算法
Strategy *strategy2 = new ConcreteStrategyB();
Context* context1 = new Context(strategy2);
context1->doAction();
//释放指针省略写
return 0;
}
2.1 优点
1. 实现和抽象分离,依赖性小
2. 用户无须知道内部细节(算法流程)的实现,只需选择想要使用的算法ConcreteStrategyA或ConcreteStrategyB.
3. 运行时运态绑定所运用的具体算法
4. 新加算法实现,无需修改抽象父类
5. 新加流程也无需修改原有流程,可在Context中新加流程方法即可。
2.2 缺点
1. 如果具体算法多,类也会很多
2. 需要增加Context增大开销成本
3. 应用场景
1. 多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为
2. 需要在不同情况下使用不同的策略算法,或策略还可能在未来用其它方式来实现
3. 对客户隐藏具体算法的细节,彼此完全独立
4 总结
策略模式,运用了面向对象设计的一个原则:优先使用组合而非继承。因此,策略模式比模版方法优秀。
多用组合而非继承原因:
1. 组合可以使用时动态决定使用哪种对象
2. 继承在C++中会增大开销(虚表等)
3. 继承修改,动一发,可能动全身
下篇预告:状态模式