设计模式之职责链模式

相信大家都玩过类似于“斗地主”的纸牌游戏,某人出牌给他的下家,下家看看手中的牌,如果要不起,则将出牌请求转发给他的下家,其下家再进行判断。一个循环下来,如果其他人都要不起该牌,则最初的出牌者可以打出新

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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

一 职责链模式概述

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120138.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JAVA设计模式初探之装饰者模式

    这个模式花费了挺长时间,开始有点难理解,其实就是定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。设计初衷:通常可以使用继承来实现功能的拓展,如果这些需要拓展的功能的种类很繁多,那么势必生成很多子类,增加系统的复杂性,同时,使用继承实现功能拓展,我们必须可预见这些拓展功能,这些功能是编译时就确定了,是静态的。…

    2022年3月11日
  • 设计模式之工厂模式建议收藏

    一普通工厂模式1.类图2.代码实现#pragmaonce#include<iostream>usingnamespacestd;//抽象渲染类classIR

    2021年12月19日
  • 23种设计模式汇总整理

    设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式结构型模式,共七种:适配器模式、装饰者模式、代理模式、外观模式、桥接模式、组合模式、享元模式。行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。其实还有两类:并发型模式和线程池模式。…

    2022年3月11日
  • 十四、迭代器模式—— 一个一个的遍历 #和设计模式一起旅行#「建议收藏」

    套路要深…故事背景今天要介绍一下迭代器,首先简单说明一下,什么是迭代器,为什么要使用迭代器。 迭代器(Iterate) 的意思就是反复做某件事情。那为什么要反复做某件事情呢,比如我们有个容器里面装了很好东西(这些东西都是同一类型的),要从容器中取每一个东西出来,就要反复去做一个取出的事情。故事主角迭代器模式 : 提供一种方法顺序访问一个聚合对象中的各个元素,而…

    2022年2月27日
  • 设计模式–代理模式(Proxy Pattern)

    设计模式–代理模式(Proxy Pattern)

    2021年7月3日
  • 设计模式23模式介绍迭代器_二十三种设计模式

    设计模式23模式介绍迭代器_二十三种设计模式一、什么是设计模式设计模式是一套被反复使用、多数人知晓的、经过分类编写的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。毫无疑问,设计模式使代码编程真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖头一样。项目中合理的运用设计模式可以完美的解决很多问题,每种模式都有响应的原理与之对应,每一个模式描述了一个在我们周围不断重复发生的问题,以及该问题…

    2022年10月25日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号