当前位置: 首页 > article >正文

重温设计模式--5、职责链模式

文章目录

      • 职责链模式的详细介绍
      • C++ 代码示例
      • C++示例代码2

职责链模式的详细介绍

在这里插入图片描述

  1. 定义与概念
    职责链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它旨在将请求的发送者和多个接收者解耦,让多个对象都有机会处理请求,这些对象就像一条链一样依次传递请求,直到有一个对象能够处理该请求为止。如果某个对象不能处理请求,它会将请求转发给链上的下一个对象。

例如,在一个员工请假审批系统中,员工提交请假申请后,可能先由小组长审批,如果请假天数较多,小组长无法审批,就会将申请转交给部门经理审批,若部门经理权限也不够,还可能继续往上传递给更高层领导审批。这里的小组长、部门经理、高层领导等就构成了一条职责链,每个角色都是链上的一环,根据自己的审批权限来决定是否处理该请假申请这个请求。

  1. 角色构成及职责

    • 抽象处理者(Handler):它定义了一个处理请求的接口,通常包含一个抽象的处理请求方法以及设置下一个处理者的方法。这个抽象类是整个职责链的基础,所有具体的处理者类都要继承自它。例如,在上述请假审批示例中,抽象处理者可以定义一个抽象的“审批请求”方法和“设置下一个审批者”的方法,无论是小组长还是部门经理等具体审批角色对应的类都要遵循这个统一的接口规范。
    • 具体处理者(ConcreteHandler):是抽象处理者的子类,实现了处理请求的具体逻辑。每个具体处理者会判断自己是否能够处理当前请求,如果可以,就进行处理;如果不行,就将请求传递给下一个处理者(通过调用设置好的下一个处理者对应的处理请求方法)。比如小组长这个具体处理者,会根据自己能审批的请假天数范围来判断是否处理员工的请假申请,若超出范围就把申请转交给部门经理这个下一个处理者。
    • 请求(Request):这是需要在职责链中传递并被处理的对象,它包含了与请求相关的各种信息,例如请假申请中的请假天数、请假事由等内容。
      在这里插入图片描述
  2. 优点

    • 降低耦合度:请求的发送者不需要知道具体是哪个对象来处理请求,它只需要将请求发送到职责链的起始端即可,而各个具体处理者之间也只是通过链的方式依次传递请求,相互之间的依赖关系比较松散,便于系统的维护和扩展。
    • 增强灵活性:可以动态地增加、删除或者重新排列职责链上的处理者,比如在请假审批系统中,如果公司组织结构调整,增加了新的管理层级或者调整了审批权限,只需要相应地修改或添加具体处理者类以及调整它们在链上的顺序就可以适应变化,而不需要大规模改动整个系统的其他部分。
    • 便于分工协作:不同的具体处理者可以专注于处理自己职责范围内的请求,符合单一职责原则,有利于代码的编写、测试以及后续的维护工作。
  3. 缺点

    • 可能导致性能问题:如果职责链比较长,而且每个请求都需要遍历较长的链才能找到合适的处理者,可能会消耗较多的时间和资源,特别是在对性能要求较高的场景下,这一点需要注意并合理优化。
    • 调试难度增加:由于请求在多个对象之间传递,当出现问题时,确定是哪个环节的处理者出现故障或者错误的处理逻辑相对复杂一些,不利于快速定位和解决问题。
  4. 应用场景

    • 审批流程:如前面提到的员工请假审批、费用报销审批等各种涉及多层级审批的场景,不同层级的审批人员构成职责链,根据审批权限来处理请求。
    • 事件处理系统:在图形用户界面开发中,比如鼠标点击事件、键盘按键事件等,不同的控件或者组件可以按照一定的顺序构成职责链,根据各自的功能和逻辑来判断是否处理这些事件,比如先由按钮控件判断是否点击在自己范围内,如果不是再由父容器等继续判断处理。
    • 客户服务系统:客户提出的问题按照问题的类型、难度等可以在不同的客服人员或者部门之间传递,例如一线客服先尝试解决简单问题,解决不了就转交给专业技术部门等,形成一条处理客户问题的职责链。

C++ 代码示例

以下是一个简单的模拟请假审批的 C++ 代码示例来体现职责链模式:

#include <iostream>
#include <string>

// 请求类,这里模拟请假申请,包含请假天数和请假事由
class LeaveRequest {
public:
    LeaveRequest(int days, const std::string& reason) : m_days(days), m_reason(reason) {}
    int getDays() const { return m_days; }
    std::string getReason() const { return m_reason; }

private:
    int m_days;
    std::string m_reason;
};

// 抽象处理者类,定义处理请求的接口以及设置下一个处理者的方法
class Handler {
public:
    Handler() : m_nextHandler(nullptr) {}
    virtual ~Handler() = default;
    void setNextHandler(Handler* next) { m_nextHandler = next; }
    virtual void handleRequest(LeaveRequest& request) = 0;

protected:
    Handler* m_nextHandler;
};

// 具体处理者 - 小组长类
class TeamLeader : public Handler {
public:
    void handleRequest(LeaveRequest& request) override {
        if (request.getDays() <= 2) {
            std::cout << "Team leader approved the leave request for " << request.getReason() << ". Days: " << request.getDays() << std::endl;
        } else if (m_nextHandler!= nullptr) {
            m_nextHandler->handleRequest(request);
        }
    }
};

// 具体处理者 - 部门经理类
class DepartmentManager : public Handler {
public:
    void handleRequest(LeaveRequest& request) override {
        if (request.getDays() <= 5) {
            std::cout << "Department manager approved the leave request for " << request.getReason() << ". Days: " << request.getDays() << std::endl;
        } else if (m_nextHandler!= nullptr) {
            m_nextHandler->handleRequest(request);
        }
    }
};

// 具体处理者 - 总经理类
class GeneralManager : public Handler {
public:
    void handleRequest(LeaveRequest& request) override {
        std::cout << "General manager approved the leave request for " << request.getReason() << ". Days: " << request.getDays() << std::endl;
    }
};

int main() {
    LeaveRequest request1(1, "Personal affairs");
    LeaveRequest request2(4, "Sick leave");
    LeaveRequest request3(8, "Family trip");

    TeamLeader teamLeader;
    DepartmentManager departmentManager;
    GeneralManager generalManager;

    teamLeader.setNextHandler(&departmentManager);
    departmentManager.setNextHandler(&generalManager);

    teamLeader.handleRequest(request1);
    teamLeader.handleRequest(request2);
    teamLeader.handleRequest(request3);

    return 0;
}

在上述代码中:

  • LeaveRequest 类作为请求对象,封装了请假天数和请假事由等信息。
  • Handler 类是抽象处理者,定义了 handleRequest 方法用于处理请求以及 setNextHandler 方法来设置下一个处理者。
  • TeamLeaderDepartmentManagerGeneralManager 分别是具体的处理者类,它们继承自 Handler 类,在 handleRequest 方法中根据自己的审批权限(这里以请假天数衡量)来决定是处理请求还是将请求传递给下一个处理者。
  • main 函数中,创建了不同的请求对象以及各个具体处理者对象,并将它们连接成职责链(通过 setNextHandler 方法),然后将请求依次发送到职责链的起始端(这里是小组长),由职责链上的处理者根据自身规则来处理请求。

C++示例代码2

#include<iostream>
#include<string>
using namespace std;
//请求
class request
{
public:
	string type;//类型
	int count;//数量
	string content;//内容
public:
	request(string m_type, int len ,string m_content):type(m_type),count(len),content(m_content){}
};
//抽象管理类
class Manger
{
protected:
	string m_name;
	Manger *super;
public:
	Manger(string name):m_name(name){}
	virtual void setsuper(Manger *m_super)
	{
		super = m_super;
	}
	virtual void requestapplication(request m_request){}
};
//经理
class jingli:public Manger
{
public:
	jingli(string name):Manger(name){}
	void requestapplication(request m_request)
	{
		if(m_request.type=="请假" && m_request.count<3)
		{
			cout<<m_name<<": "<<m_request.content<<"数量:"<<m_request.count<<" 批准"<<endl;
		}
		else
		{
			super->requestapplication(m_request);
		}
	}
};
//主管
class zhuguan:public Manger
{
public:
	zhuguan(string name):Manger(name){}
	void requestapplication(request m_request)
	{
		if(m_request.type=="请假" && m_request.count<5)
		{
			cout<<m_name<<": "<<m_request.content<<"数量:"<<m_request.count<<" 批准"<<endl;
		}
		else
		{
			super->requestapplication(m_request);
		}
	}
};
//总经理
class zongjingli:public Manger
{
public:
	zongjingli(string name):Manger(name){}
	void requestapplication(request m_request)
	{
		if(m_request.type=="请假" && m_request.count<10)
		{
			cout<<m_name<<": "<<m_request.content<<"数量:"<<m_request.count<<" 批准"<<endl;
		}
		else
		{
			cout<<m_name<<": "<<m_request.content<<"数量:"<<m_request.count<<" 不批准"<<endl;
		}
	}
};
int main()
{
	request *myrequest = new request("请假" ,6,"小明请假");
	jingli *m_jingli = new jingli("经理");
	zhuguan*m_zhuguan = new zhuguan("主管");
	zongjingli *m_zongjingli = new zongjingli("总经理");

	m_jingli->setsuper(m_zhuguan);
	m_zhuguan->setsuper(m_zongjingli);

	m_jingli->requestapplication(*myrequest);
	myrequest->count=100;
	cout<<endl;
	m_jingli->requestapplication(*myrequest);
	myrequest->count=1;
	cout<<endl;
	m_jingli->requestapplication(*myrequest);
	return 0;
}


http://www.kler.cn/a/452642.html

相关文章:

  • 编译openssl遇到错误Parse errors: No plan found in TAP output的解决方法
  • OpenCV相机标定与3D重建(36)计算两幅图像之间基本矩阵(Fundamental Matrix)的函数findFundamentalMat()的使用
  • 选择屏幕的用法
  • oracle linux8.10+ oracle 23ai安装
  • docker commit生成的镜像瘦身
  • OAuth 2.0
  • 基于 Nginx 的网站服务器与 LNMP 平台搭建指南
  • 使用ForceBindIP绑定应用到指定IP
  • 第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书正式赛题
  • 【Redis】配置序列化器
  • 每天40分玩转Django:Django管理界面
  • 「下载」智慧产业园区-数字孪生建设解决方案:重构产业全景图,打造虚实结合的园区数字化底座
  • 鸿蒙项目云捐助第二十一讲云捐助项目物联网IoT模拟器的使用
  • (ES Modules)prettier格式化typescript源码
  • ubuntu 如何重装你的apt【apt-get报错: symbol lookup error/undefined symbol】
  • SpringBoot Restful接口同时支持多个文件上传和参数传递
  • 要查询 `user` 表中 `we_chat_subscribe` 和 `we_chat_union_id` 列不为空的用户数量
  • springboot473基于web的物流管理系统(论文+源码)_kaic
  • xshell 隧道
  • 华为手机建议使用adb卸载的app
  • NTLM 中继到 LDAP 结合 CVE-2019-1040 接管全域
  • Ubuntu安装教程+网页部署于服务器(前端+后端+mysql数据库)新版
  • leetcode之hot100---2两数相加(C++)
  • 网络安全等级自我评价
  • 卷积神经网络入门指南:从原理到实践
  • 国产云厂商数据库产品--思维导图