设计模式之职责链模式

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

大家好,又见面了,我是全栈君,今天给大家准备了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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 设计模式(一)工厂模式Factory(创建型)

    设计模式(一)工厂模式Factory(创建型)设计模式一工厂模式Factory在面向对象编程中,最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下,new操作符直接生成对象会带来一些问题。举例来说,许多类型对象的创造需要一系列的步骤:你可能需要计算或取得对象的初始设置;选择生成哪个子对象实例;或在生成你需要的对象之前必须先生成一些辅助功能的对象。在这些………

    2022年7月20日
    19
  • 设计模式:组合模式

    设计模式:组合模式

    2022年1月18日
    45
  • JAVA设计模式之单例模式

    本文继续介绍23种设计模式系列之单例模式。概念:  java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、登记式单例。  单例模式有以下特点:  1、单例类只能有一个实例。  2、单例类必须自己创建自己的唯一实例。  3、单例类必须给所有其他对象提供这一实例。  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例…

    2022年3月11日
    40
  • [设计模式]委派模式「建议收藏」

    github地址:https://github.com/1711680493点我进入github如需了解更多设计模式,请进入我的设计模式专栏委派模式委派模式不是23设计模式中的一种.与策略模式很相似.拥有以下三种角色抽象任务角色 委派者角色 具体任务角色委派模式,就是将任务发给委派者角色,委派者角色去委派具体任务角色委派模式对外隐藏了具体实现,仅将委派者角色暴露给外部委派模式和策略模式不同的是,委派者角色和具体任务角色都要继承/实现抽象任务角色Spring框架很

    2022年4月16日
    43
  • 软件架构与设计模式_软件架构设计

    软件架构与设计模式_软件架构设计什么是架构?软件体系结构通常被称为架构,指可以预制和可重构的软件框架结构。架构尚处在发展期,对于其定义,学术界尚未形成一个统一的意见,而不同角度的视点也会造成软件体系结构的不同理解,以下是一些主流的标准观点。ANSI/IEEE610.12-1990软件工程标准词汇对于体系结构定义是:“体系架构是以构件、构件之间的关系、构件与环境之间的关系为内容的某一系统的基本组…

    2022年8月31日
    5
  • 十八、职责链模式-推卸责任,不关我的事,我不管!#和设计模式一起旅行#

    不在其位,不谋其政! –出自《论语·泰伯》故事背景在现实世界中,有很多情况下会遇到一些推卸责任的场景,比如要办理一件事的时候,被告诉你要去做个做这个事情,但是去了这个地方,确告诉要到另一个地方去,最后搞了很久,才办完这一件事。这种情况下,就可以简单的称为踢皮球,也就是推卸责任。在软件中,当外部请求程序进行某个出来,这个程序无法处理就把该请求转给其他对象负责,当对个对象组…

    2022年2月27日
    37

发表回复

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

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