前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++职责链模式

C++职责链模式

原创
作者头像
Sky_Mao
修改2020-08-27 10:20:21
5120
修改2020-08-27 10:20:21
举报

一、概述

模式名称:

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;
}

运行结果:

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

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

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

此示例的对象结构如下:

对象交互图
对象交互图

对象交互时序图:

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 运行结果:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档