C++职责链模式

2020-08-27 10:20:21 浏览数 (1)

一、概述

模式名称:

CHAIN OF RESPONSIBILITY(职责链) (对象行为型模式)

意图:

使多个对象都有机会处理同一个请求,从而避免发送者和接受者之间的耦合关系。这些处理请求的对象组成一条链,

并沿着这条链传递该请求,直到有一个对象处理它,或者传递到最后一个节点,结束该链。

适用性:

1、有多个对象可以处理同一个请求,哪个对象处理该请求只有运行时才能确定。

2、想要在不明确指定接受者的情况下,向多个对象中的一个发送请求。

3、发送者只需要发送请求,而不用关注哪个对象会处理该次请求。

结构:

职责链模式结果图职责链模式结果图

效果:

1、降低耦合度 该模式使一个对象无需知道是哪一个对象处理其请求。

2、增强了对象处理职责的灵活性,可以动态的添加或删除某些节点,来实现对象职责的动态变化。

3、不保证每次请求都会被处理

二、代码示例

这里举一个例子来深入了解职责链模式,我们假设有这么一个业务需求,根据输入的表达式,来进行加减乘除的处理。

输入的表达式为:a b,a-b,a*b,a/b

按照职责链的结构图,我们来设计一下这个业务的结构图:

示例类图示例类图

根据类图生成代码:

接口类:

代码语言:javascript复制
class ICalculate
{
public:
    virtual int oCalc(const string& strRequest) = 0;
};

加法处理类:

代码语言:javascript复制
//plus
class CPlusCalc : public ICalculate
{
public:
    CPlusCalc(ICalculate* pCalc) : m_pCalc(pCalc) {};
    ~CPlusCalc() {if (nullptr != m_pCalc)
    {
        delete m_pCalc;
        m_pCalc = nullptr;
    }
    };

    virtual int oCalc(const string& strRequest) override
    {
        int nFind = strRequest.find(" ");
        if (-1 != nFind)
        {
            cout << "加法处理" << endl;
            string strLeft = strRequest.substr(0, nFind);
            string strRight = strRequest.substr(nFind   1, strRequest.size() - nFind);

            int nL = stoi(strLeft);
            int nR = stoi(strRight);

            int nResult = nL   nR;

            return nResult;
        }
        else
        {
            if (nullptr != m_pCalc)
            {
                return m_pCalc->oCalc(strRequest);
            }

            return -1;
        }
    };

private:
    ICalculate* m_pCalc = nullptr;
};

减法处理类:

代码语言:javascript复制
//minus
class CMinusCalc : public ICalculate
{
public:
    CMinusCalc(ICalculate* pCalc) : m_pCalc(pCalc) {};
    ~CMinusCalc() {
        if (nullptr != m_pCalc)
        {
            delete m_pCalc;
            m_pCalc = nullptr;
        }
    };

    virtual int oCalc(const string& strRequest) override
    {
        int nFind = strRequest.find("-");
        if (-1 != nFind)
        {
            cout << "减法处理" << endl;
            string strLeft = strRequest.substr(0, nFind);
            string strRight = strRequest.substr(nFind   1, strRequest.size() - nFind);

            int nL = stoi(strLeft);
            int nR = stoi(strRight);

            int nResult = nL - nR;

            return nResult;
        }
        else
        {
            if (nullptr != m_pCalc)
            {
                return m_pCalc->oCalc(strRequest);
            }

            return -1;
        }
    };

private:
    ICalculate* m_pCalc = nullptr;
};

乘法处理类:

代码语言:javascript复制
//multiply
class CMultiplyCalc : public ICalculate
{
public:
    CMultiplyCalc(ICalculate* pCalc) : m_pCalc(pCalc) {};
    ~CMultiplyCalc() {
        if (nullptr != m_pCalc)
        {
            delete m_pCalc;
            m_pCalc = nullptr;
        }
    };

    virtual int oCalc(const string& strRequest) override
    {
        int nFind = strRequest.find("*");
        if (-1 != nFind)
        {
            cout << "乘法处理" << endl;
            string strLeft = strRequest.substr(0, nFind);
            string strRight = strRequest.substr(nFind   1, strRequest.size() - nFind);

            int nL = stoi(strLeft);
            int nR = stoi(strRight);

            int nResult = nL * nR;

            return nResult;
        }
        else
        {
            if (nullptr != m_pCalc)
            {
                return m_pCalc->oCalc(strRequest);
            }

            return -1;
        }
    };

private:
    ICalculate* m_pCalc = nullptr;
};

除法处理类:

代码语言:javascript复制
//divide
class CDivideCalc : public ICalculate
{
public:
    CDivideCalc(ICalculate* pCalc) : m_pCalc(pCalc) {};
    ~CDivideCalc() {
        if (nullptr != m_pCalc)
        {
            delete m_pCalc;
            m_pCalc = nullptr;
        }
    };

    virtual int oCalc(const string& strRequest) override
    {
        int nFind = strRequest.find(R"(/)");
        if (-1 != nFind)
        {
            cout << "除法处理" << endl;
            string strLeft = strRequest.substr(0, nFind);
            string strRight = strRequest.substr(nFind   1, strRequest.size() - nFind);

            int nL = stoi(strLeft);
            int nR = stoi(strRight);

            if (0 == nR)
            {
                cout << "除数不可为0" << endl;
                return -1;
            }
            int nResult = nL / nR;
            
            return nResult;
        }
        else
        {
            if (nullptr != m_pCalc)
            {
                return m_pCalc->oCalc(strRequest);
            }

            return -1;
        }
    };

private:
    ICalculate* m_pCalc = nullptr;
};

职责链的创建:

代码语言:javascript复制
CDivideCalc* pDC = new CDivideCalc(nullptr);
CMultiplyCalc* pMUC = new CMultiplyCalc(pDC);
CMinusCalc* pMIC = new CMinusCalc(pMUC);
ICalculate* pCalc = new CPlusCalc(pMIC);

main函数:

代码语言:javascript复制
int main()
{
    //创建职责链
    CDivideCalc* pDC = new CDivideCalc(nullptr);
    CMultiplyCalc* pMUC = new CMultiplyCalc(pDC);
    CMinusCalc* pMIC = new CMinusCalc(pMUC);
    ICalculate* pCalc = new CPlusCalc(pMIC);

    while (true)
    {
        string strRequest = "";
        cin >> strRequest;

        if (strRequest.empty())
        {
            break;
        }

        if (-1 != strRequest.find("exit"))
        {
            break;
        }

        int nCalcResult = pCalc->oCalc(strRequest);
        cout << "结果:" << nCalcResult << endl;
    }
    delete pCalc;
}

运行结果:

示例运行结果示例运行结果

计算公式不需要知道那个计算对象会处理我的请求,请求的发送者与受理者是松耦合的状态,职责链的对象可以调整顺序,添加和删除功能。不需要修改客户端的代码。

也不会影响到职责链中其他对象的实现。

此示例的对象结构如下:

对象交互图对象交互图

对象交互时序图:

对象交互时序图对象交互时序图

0 人点赞