【学习笔记】C++设计模式_CH4_策略模式

策略模式:Strategy

    • 动机
    • 代码示例
    • 要点总结

本博文由 youngpan1101 出品,转载请注明出处。
文章链接:https://blog.csdn.net/youngpan1101/article/details/105503352
作者: 宋洋鹏(youngpan1101)
邮箱: [email protected]

ps:该笔记是基于《C++设计模式 [李建忠]》的学习笔记 [视频链接] [源码和PPT资料下载]

  • Head First设计模式读书总结——策略模式
  • Head First_设计模式_学习笔记_第01章_策略模式 C++

动机

  • 软件构建中,对象使用的算法种类多样,且具有常变属性,如果将这些算法都编码到对象中,将会使得对象变得异常复杂,有时支持不使用的算法也是一个性能负担;
  • 如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

代码示例

  1. strategy1.cpp
enum TaxBase {
	CN_Tax,
	US_Tax,
	DE_Tax,
	FR_Tax       //更改
};

class SalesOrder{
    TaxBase tax;
public:
    double CalculateTax(){
        //...
        
        if (tax == CN_Tax){
            //CN***********
        }
        else if (tax == US_Tax){
            //US***********
        }
        else if (tax == DE_Tax){
            //DE***********
        }
		else if (tax == FR_Tax){  //更改:违背了 开闭原则, 对扩展开放,对更改关闭
			//...
		}

        //....
     }
    
};

  1. strategy2.cpp 【更为合适的实现

class TaxStrategy{
public:
    virtual double Calculate(const Context& context)=0;
    virtual ~TaxStrategy(){}  // 虚析构函数,否则多态 delete 会有问题
};


class CNTax : public TaxStrategy{
public:
    virtual double Calculate(const Context& context){
        //***********
    }
};

class USTax : public TaxStrategy{
public:
    virtual double Calculate(const Context& context){
        //***********
    }
};

class DETax : public TaxStrategy{
public:
    virtual double Calculate(const Context& context){
        //***********
    }
};

//扩展
//*********************************
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); //多态调用
        //...
    }
    
};

要点总结

  • 需要从时间轴上来考虑软件构建过程,比如说上面示例中的 Tax 会在将来支持不同的国家
  • 基类务必要有虚析构函数,否则多态 delete 会有问题
  • 指针来是实现多态的变量
  • 上面示例,后者方法的好处:如果增加一个 France Tax 的处理,只需要扩展一个 class FRTax, 而 class SalesOrder 没有发生修改,遵循开放封闭原则
  • 面向对象中的复用:是编译之后,二进制文件的复用
  • 在 if-else 后面添加代码,往往会打破原有的代码逻辑,引入新的 bug
  • 策略模式:定义一系列算法,把他们一个个封装起来,并且使它们可互相替换(变化)。该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)
    • Strategy 及其子类为组件提供了一系列可重用的算法,从而使类型在运行时方便地根据需要在各个算法之间进行切换
    • Strategy 模式提供了用条件判断语句之外的另一种选择,消除条件判断语句(结构化,分而治之的写法),就是在解耦,含有许多条件判断语句的代码通常都需要 Strategy 模式
    • 如果 Strategy 对象没有实例变量,那么各个上下文可以共享同一个 Strategy 对象,从而节省对象开销

你可能感兴趣的:(设计模式,设计模式,c++)