zoukankan      html  css  js  c++  java
  • 设计模式之职责链模式

      相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断。一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新牌。在这个过程中,纸牌作为一个请求沿着一条链在传递,每一位纸牌的玩家都可以处理该请求。在设计模式中,也有一种专门用于处理这种请求链式的模式,它就是职责链模式。

    一 职责链模式概述

    1.1 职责链模式简介

    职责链(Chain of Responsibility)模式:避免将请求发送者与接受者耦合在一起,让多个对象都有机会接受请求,将这些对象连成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为型模式。  

    1.2 需求

    需求背景:M公司承接了某企业SCM(Supply Chain Management,供应链管理)系统的开发任务,其中包含一个采购审批子系统。该企业的采购审批是分级进行的,即根据采购金额的不同由不同层次的主管人员来审批:主任可以审批5万元以下(不包括5万)的采购单,副董事长可以审批5万~10万(不包括10万)的采购单,50万元以及以上的采购单就需要开董事会讨论决定,如下图所示:

    1.3 类图

      

    1.4 代码实现

    1.4.1 抽象执行者类

    // 抽象执行者类
    class AbstractApprover
    {
    public:
        explicit AbstractApprover(string strName = ""){} // 防止隐式转换
        virtual ~AbstractApprover(){}
    
        void SetSucessor(AbstractApprover* pSucessor)
        {
            m_pSucessor = pSucessor;
        }
    
        virtual void ProcessRequest(CRequestX *) = 0;
    
    protected:
        string m_strName;
        AbstractApprover* m_pSucessor;
    };

    1.4.2 主管类

    // 主管类
    class CDirector : public AbstractApprover
    {
    public:
        explicit CDirector(string strName = "")
        {
            m_strName = strName;
        }
    
        ~CDirector(){}
    
        void ProcessRequest(CRequestX *pRequest)
        {
            if (pRequest->m_fAmount < 50000)
            {
                cout << "主管:"<< m_strName.c_str() << "审批采购单:" << pRequest->m_strNumber.c_str() << " " << 
                    pRequest->m_fAmount << " " << "元," << "采购目的" << pRequest->m_strPurpose.c_str() << endl;
            }
            else
            {
                m_pSucessor->ProcessRequest(pRequest);
            }
        }    
    };

    1.4.3 副总裁类

    // 副总裁类
    class CVicePresident : public AbstractApprover
    {
    public:
        explicit CVicePresident(string strName = "")
        {
            m_strName = strName;
        }
    
        ~CVicePresident(){}
    
        void ProcessRequest(CRequestX *pRequest)
        {
            if (pRequest->m_fAmount < 100000)
            {
                cout << "副总裁:"<< m_strName.c_str() << "审批采购单:" << pRequest->m_strNumber.c_str() << " " << 
                    pRequest->m_fAmount << " " << "元," << "采购目的" << pRequest->m_strPurpose.c_str() << endl;
            }
            else
            {
                m_pSucessor->ProcessRequest(pRequest);
            }
        }    
    };

    1.4.4 总裁类

    // 总裁类
    class CPresident : public AbstractApprover
    {
    public:
        explicit CPresident(string strName = "")
        {
            m_strName = strName;
        }
    
        ~CPresident(){}
    
        void ProcessRequest(CRequestX *pRequest)
        {
            if (pRequest->m_fAmount < 500000)
            {
                cout << "总裁:"<< m_strName.c_str() << "审批采购单:" << pRequest->m_strNumber.c_str() << " " << 
                    pRequest->m_fAmount << " " << "元," << "采购目的" << pRequest->m_strPurpose.c_str() << endl;
            }
            else
            {
                m_pSucessor->ProcessRequest(pRequest);
            }
        }    
    };

    1.4.5 董事会类

    // 董事会类
    class CCongress : public AbstractApprover
    {
    public:
        explicit CCongress(string strName = "")
        {
            m_strName = strName;
        }
    
        ~CCongress(){}
    
        void ProcessRequest(CRequestX *pRequest)
        {
            cout << "董事会:"<< m_strName << "审批采购单:" << pRequest->m_strNumber << " " << 
                pRequest->m_fAmount << " " << "元," << "采购目的" << pRequest->m_strPurpose << endl;
        }    
    };

    1.5 测试

    #include "stdio.h"
    
    #include "responsibility.h"
    
    void main()
    {
        // 创建职责链
        AbstractApprover *PDirector = new CDirector("主管");
        AbstractApprover *pVicePresident = new CVicePresident("副总裁");
        AbstractApprover *pPresident = new CPresident("总裁");
        AbstractApprover *pCongress = new CCongress("董事会");
    
        PDirector->SetSucessor(pVicePresident);
        pVicePresident->SetSucessor(pPresident);
        pPresident->SetSucessor(pCongress);
    
        // 构造采购请求单并发送审批请求
        CRequestX* request1 = new CRequestX(45000.00,
            "MANULIFE201706001",
            "购买PC和显示器");
        PDirector->ProcessRequest(request1);
    
        CRequestX* request2 = new CRequestX(60000.00,
            "MANULIFE201706002",
            "2017开发团队活动");
        PDirector->ProcessRequest(request2);
    
        CRequestX* request3 = new CRequestX(160000.00,
            "MANULIFE201706003",
            "2017公司年度旅游");
        PDirector->ProcessRequest(request3);
    
        CRequestX* request4 = new CRequestX(800000.00,
            "MANULIFE201706004",
            "租用新临时办公楼");
        PDirector->ProcessRequest(request4);
    
        return;
    }

    二 职责链模式总结

    2.1 主要优点

      (1)使得一个对象无需知道是其他哪一个对象处理其请求,对象仅需知道该请求会被处理即可,且链式结构由客户端创建 => 降低了系统的耦合度

      (2)在系统中增加一个新的具体处理者无须修改原有系统源代码,只需要在客户端重新建立链式结构即可 => 符合开闭原则

    2.2 主要缺点

      (1)由于一个请求没有一个明确地接受者 => 无法保证它一定会被处理

      (2)对于较长的职责链 => 系统性能有一定影响且不利于调试

      (3)如果建立链不当,可能会造成循环调用 => 导致系统进入死循环

    2.3 应用场景

      (1)有多个对象处理同一个请求且无需关心请求的处理对象时谁以及它是如何处理的 => 比如各种审批流程

      (2)可以动态地指定一组对象处理请求,客户端可以动态创建职责链来处理请求,还可以改变链中处理者之间的先后次序 => 比如各种流程定制

  • 相关阅读:
    第2讲——处理数据
    第1讲——用C++写一个程序
    数论18——反演定理(莫比乌斯反演)
    数论17——反演定理(二项式反演)
    数论16——母函数
    数论15——抽屉原理
    数论14——容斥原理
    数论13——康托展开
    com.opensymphony.xwork2.config.ConfigurationManager.addConfigurationProvider
    Tomcat的杂七杂八
  • 原文地址:https://www.cnblogs.com/xiaobingqianrui/p/9019846.html
Copyright © 2011-2022 走看看