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

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

文章目录

      • 职责链模式的详细介绍
      • 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/450139.html

相关文章:

  • 四种电子杂志制作软件
  • Unity3D仿星露谷物语开发5之角色单例模式
  • hCaptcha 图像识别 API 对接说明
  • 【CryptoJS库AES加密】
  • 24/12/24 力扣每日一题 # LeetCode 524. 通过删除字母匹配到字典里最长单词 全网最详细解释
  • Docker搭建kafka环境
  • Android基于Path的addRoundRect,Canvas剪切clipPath简洁的圆角矩形实现,Kotlin(1)
  • CS!GO
  • 灰度测试是什么
  • 【NLP 17、NLP的基础——分词】
  • 用套接字的UDP,TCP知道什么是HTTP吗?
  • Apache解析漏洞(apache_parsing_vulnerability靶场攻略CVE-2017-15715靶场攻略)
  • 服务平滑发布与线上验证
  • CNN、RNN、LSTM和Transformer之间的区别和联系
  • 安装CPU版的torch(清华源)
  • 经典案例PPT | 大型水果连锁集团新零售数字化建设方案
  • Ubuntu下C语言操作kafka示例
  • 基于GRU门控循环神经网络的多分类预测【MATLAB】
  • npm error code ETIMEDOUT
  • 【Prometheus】【实战篇(七)】在 Grafana 中配置数据源并使用 Prometheus Node Exporter
  • 【研究生必备|学术会议|高录用|见刊后1个月检索】第三届材料科学与智能制造国际学术会议(MSIM2025)
  • 【橘子微服务】spring cloud function的编程模型
  • Webhook 是什么?详解其工作原理
  • 日文医学论文如何翻译
  • EMQX构建简易的云服务
  • 节日需求激增:如何抓住家居用品和圣诞装饰品市场的商机?