设计模式C++002__策略模式

设计模式C++002__策略模式

1、动机:

在软件构建过程中,某些对象使用的算法是多种多样的,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

?如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

2、策略模式:

定义一系列算法,把他们一个个封装起来,并且使他们可互相替换(变化)。该模式使得算法可以独立于使用它的客户程序(稳定)而变化(扩展,子类)。--GoF

例如跨国电商公司,订单计算税费的功能。
前期只有3个国家的业务,就只定义3个算法,使用枚举类区分。如果要在新的国家扩展业务。改动代码出如下,枚举定义处要改,还要在订单类里添加新的计算方法。
违反了开闭原则。

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){  //更改
			//...
		}

        //....
     }
    
};

如果使用策略模式,定义一个税费计算抽象基类,基类中只有一个计算税费的虚方法,不同国家的税费计算方法继承自抽象基类,各自实现自己的税费计算方法。
如果要支持新的税费计算方法,只需新建一个子类,根据实际情况实现即可。调用时利用C++的多态性质,在主函数中父类的指针指向子类对象,再用指针调用计算税费方法。
理论上,只要是if-else, switch-case 中可能会扩展新的分支以支持业务。都可以改为策略模式。

class TaxStrategy{
public:
    virtual double Calculate(const Context& context)=0;
    virtual ~TaxStrategy(){}
};


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;  //这里声明一个虚基类指针,访问类型为private

public:
    SalesOrder(StrategyFactory* strategyFactory){
        this->strategy = strategyFactory->New Strategy();//这里就是子类实例对象的产生的地方,可能是一个工厂方法产生的。
    }
    ~SalesOrder(){
        delete this->strategy;
    }

    public double CalculateTax(){
        //...
        Context context();
        
        double val = 
            strategy->Calculate(context); //多态调用
        //...
    }
    
};

3、策略模式相比 if-else这种分支处理。可以在不改变原有类的基础上,只新增子类,就可以实现对原有功能的扩展。符合开闭原则。

实际上,这也是利用了晚绑定的原理,调用哪一种方法。
结构:

4、要点总结:

  • Strategy及其子类为组提供了一些列可重用的算法,从而使得类型在运行时方便的根据需要再各个算法之间进行切换。
  • Strategy模式同了用条件判断语句以外的一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。
posted @ 2024-07-25 19:11  wjwdive  阅读(3)  评论(0编辑  收藏  举报