“组件协作”模式之策略模式

发布于:2025-06-26 ⋅ 阅读:(18) ⋅ 点赞:(0)

策略模式

引例

税务计算系统,根据各个国家的税法,进行税务计算。各个国家税法规定差别很大,需对应进行相应的实现。

  • 常规解耦前写法
    使用if-else语句或switch-case语句进行结构化分而治之且有增加的扩展变化需求可能,扩展新的需求不方便。
    // 税务类型 枚举类型
    enum TaxBase
    {
    	CN_Tax,
    	US_Tax,
    	DE_Tax,
    	// 扩展,更改变化点
    	FR_Tax
    };
    
    class SalesOrder
    {
    	TaxBase tax;
    public:
    	double CalculateTax()
    	{
    		...
    		if(tax == CN_Tax)
    		{
    			// 中国税务计算实现
    			...
    		}
    		else if(tax == US_Tax)
    		{
    			// 美国税务计算实现
    		}
    		else if(tax == DE_Tax)
    		{
    			// 德国税务计算实现
    			...
    		}
    		// 增加拓展法国,以下为更改变化点
    		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)
    	{
    		// 中国税务计算实现
    		...
    	}
    };
    
    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(StrateFactory* strateFactory)
    	{
    		this->strategy = strategyFactory->NewStrategy();
    	}
    	~SalesOrder()
    	{
    		delete this->strategy;
    	}
    	double CalculateTax()
    	{
    		...
    		Context context();
    		double val = strategy->Calculate(context);	// 多态调用
    		...
    	}
    }
    

动机 Motivation

  • 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;有时支持不使用的算法也是一个性能负担。
  • 策略模式可以在运行时根据需要透明地更改对象的算法,将算法与对象本身解耦

模式定义

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

结构

在这里插入图片描述
红色部分为稳定部分,蓝色部分为变化部分。

要点总结

  • Strategy及其子类为组件提供了一系列可重用的算法,从而可以使
    得类型在运行时方便地根据需要在各个算法之间进行切换。
  • Strategy模式提供了用条件判断语句以外的另一种选择,消除条件
    判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需
    要Strategy模式。
  • 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个
    Strategy对象,从而节省对象开销。

来源:极客班——C++设计模式入门


网站公告

今日签到

点亮在社区的每一天
去签到