策略模式-Strategy Method(C++语言描述)

我们如何看待设计模式?

设计模式需要站在时间轴上来看待,需要看到未来。如果一个系统是静态的,那我们也不需要设计模式,毕竟引入了某种设计模式之后,系统的复杂性以及可理解性就会大打折扣。

策略模式

在软件设计的过程中,某些对象使用的算法可能多种多样,经常会发生改变,如果将这些算法都硬编码到对象中,通过 if…else… 或者 switch…case… 来进行管理,将会使对象变得臃肿。

策略模式要解决的问题就是如何在运行时根据需要透明地更改对象所使用的算法?将对象与算法解耦,从而避免上述问题。

场景模拟

例如我们有一个零售销售品工单的场景,工单里面需要计算税收,于是就存在按照不同国家税收政策进行税收计算的工单。

一开始我们用枚举来标识不同国家的税务类型,用switch…case… 来进入不同的算法分支进行税务计算,代码如下。

#ifndef _SALES_ORDER_H_
#define _SALES_ORDER_H_

enum TaxType{
    CN_TAX,
    US_TAX,
    UK_TAX
    //....如果增加税收品种就在这里扩展
};

class SalesOrder{

public:

    SalesOrder():m_iTaxTyoe(-1){}

    SalesOrder(TaxType taxtype):m_iTaxTyoe(taxtype){}

    void setTaxTye(TaxType taxtype)//设置税收政策
    {
        m_iTaxTyoe = taxtype;
    }

    void calculateTax()
    {
        switch (m_iTaxTyoe)
        {
        case CN_TAX:
            /* 中国税务算法 */
            break;
        case US_TAX:
            /* 美国税务算法 */
            break;
        case UK_TAX:
            /* 英国税务算法 */
            break;
        //如果税收种类增加,则在这里增加case...
        default:
            /*未定义*/
            break;
        }
    }

    //....

private:
    int m_iTaxTyoe;
};

#endif

实际上,如果我们业务是静态的不需要再进行业务扩展变化的话,这样写也就足够了。
但实际上公司要发展,业务要拓展,后面我们就可能会引入德国的税收算法、日本的税收算法等等。那时候如果我们需要扩展我们的代码的话,就需要在枚举下面新增,以及我们的**switch…case…**下面新增对应case。

我们梳理一下思路,上述场景变化的地方在于税收算法,我们工单类与算法存在依赖关系。于是我们可以把税率算法提取出来一个税率算法抽象类,让工单类依赖于这个税率算法抽象类。UML图大致如下:

代码实现(C++)

工单类:

/*filename:SalesOrder.h*/
#ifndef _SALES_ORDER_H_
#define _SALES_ORDER_H_
#include "ITaxalgorithm.h"

class TaxContext{};//税率计算上下文

class SalesOrder
{
public:
    SalesOrder(ITaxalgorithm* pTax = nullptr):m_pTax(pTax){}

    ~SalesOrder(){}

    void setTaxType(ITaxalgorithm* pTax)
    {
        m_pTax = pTax;
    }
    void calculateTax()
    {
        TaxContext context;
        if(m_pTax)
        {
            m_pTax->calculate(context);//多态调用
        }
    }
private:
    ITaxalgorithm* m_pTax;//税率算法基类指针
};

#endif

税率算法抽象类:

/*filename:ITaxalgorithm.h*/
#ifndef _ITAXALGORITHM_H_
#define _ITAXALGORITHM_H_

class TaxContext;//税率计算上下文

class ITaxalgorithm{

public:
    virtual void calculate(const TaxContext & context);
    virtual ~ITaxalgorithm();
};

#endif

具体算法类:

/*filename:CNTax.h*/
#ifndef _ITAXALGORITHM_H_
#define _ITAXALGORITHM_H_

class TaxContext;//税率计算上下文

class ITaxalgorithm{

public:
    virtual void calculate(const TaxContext & context);
    virtual ~ITaxalgorithm();
};

#endif

使用,构造一个以中国税率算法计算的工单:

/*filename:main.cc*/
#include "CNTax.h"
#include "SalesOrder.h"

int main()
{
    CNTax cntax;
    SalesOrder order;
    order.setTaxType(&cntax);
    order.calculateTax();
    return 0;
}
总结:

可以看出,设计模式主要还是抓住系统中的不变,以时间轴来看,把将来可能会变动的地方剥离出来,提取出一个抽象类,让其他组件来依赖这个抽象类而不是具体的某个实现,从而达到模块解耦的目的。

注意:

我们这里说的依赖若不做特殊说明皆是指编译时依赖,而非运行时依赖。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值