设计模式------策略模式学习记录
动机
-
在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。
-
如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
个人理解:简单来说就是拒绝在源代码上进行扩展新功能,用类(继承)的方式对功能进行增加看代码。
优缺点(copy他人)
-
主要优点如下:
-
策略模式提供了对“开闭原则”的完美支持,用户可以在不 修改原有系统的基础上选择算法或行为,也可以灵活地增加 新的算法或行为。
-
策略模式提供了管理相关的算法族的办法。
-
策略模式提供了可以替换继承关系的办法。
-
使用策略模式可以避免使用多重条件转移语句。
-
主要缺点如下:
-
客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
-
策略模式将造成产生很多策略类,可以通过使用享元模式在一 定程度上减少对象的数量。
定义
- 定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化) ——《设计模式》GoF
代码
// 税法列子 最初的设计 用枚举方式 违背了开闭原则 扩展不能在源代码上修改
// 如果需要加另外的国家就需要i在上面进行添加 比如增加 FR_Iax
enum TaxBase {
CN_Tax,
US_Tax,
DE_Tax,
FR_Tax //更改 在此如果需要增加就需要在源代码上修改
};
class SalesOrder{
TaxBase tax;
public:
SalesOrder(){
tax = ?;
}
double CalculateTax(){
//...
if (tax == CN_Tax){
//CN***********
}
else if (tax == US_Tax){
//US***********
}
else if (tax == DE_Tax){
//DE***********
}
else if (tax == FR_Tax){ //更改
//...
}
//....
}
};
修改之后
class TaxStrategy{
public:
virtual double Calculate(const Context& context)=0;
virtual ~TaxStrategy(){}
};
class CNTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//CN***********
}
};
class USTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//US***********
}
};
class DETax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//DE***********
}
};
//扩展 增加 FRTax
//*********************************
class FRTax : public TaxStrategy{
public:
virtual double Calculate(const Context& context){
//.........
}
};
class SalesOrder{
private:
TaxStrategy* strategy; //一般是指针 体现多态性
public:
SalesOrder(StrategyFactory* strategyFactory){ //外部传参进来
this->strategy = strategyFactory->NewStrategy();
}
~SalesOrder(){
delete this->strategy;
}
public double CalculateTax(){
//...
Context context();
double val =
strategy->Calculate(context); //多态调用
//...
}
};
结构图
总结 (同上文 copy 附带 适用场景)
在策略模式中定义了一系列算法,将每一个算法封装起来,并让它们 可以相互替换。策略模式让算法独立于使用它的客户而变化,也称为 政策模式。策略模式是一种对象行为型模式。
• 策略模式包含三个角色:环境类在解决某个问题时可以采用多种策略, 在环境类中维护一个对抽象策略类的引用实例;抽象策略类为所支持 的算法声明了抽象方法,是所有策略类的父类;具体策略类实现了在 抽象策略类中定义的算法。
• 策略模式是对算法的封装,它把算法的责任和算法本身分割开,委派 给不同的对象管理。策略模式通常把一个系列的算法封装到一系列的 策略类里面,作为一个抽象策略类的子类。
• 策略模式主要优点在于对“开闭原则”的完美支持,在不修改原有系 统的基础上可以更换算法或者增加新的算法,它很好地管理算法族, 提高了代码的复用性,是一种替换继承,避免多重条件转移语句的 实现方式;其缺点在于客户端必须知道所有的策略类,并理解其区 别,同时在一定程度上增加了系统中类的个数,可能会存在很多策 略类。
• 策略模式适用情况包括:在一个系统里面有许多类,它们之间的区 别仅在于它们的行为,使用策略模式可以动态地让一个对象在许多 行为中选择一种行为;一个系统需要动态地在几种算法中选择一种; 避免使用难以维护的多重条件选择语句;希望在具体策略类中封装 算法和与相关的数据结构。
适用场景
- 如果在一个系统里面有许多类,它们之间的区别仅在于它们 的行为,那么使用策略模式可以动态地让一个对象在许多行 为中选择一种行为。
- 一个系统需要动态地在几种算法中选择一种。
- 如果一个对象有很多的行为,如果不用恰当的模式,这些行 为就只好使用多重的条件选择语句来实现。
- 不希望客户端知道复杂的、与算法相关的数据结构,在具体 策略类中封装算法和相关的数据结构,提高算法的保密性与 安全性。