【声明】本题目来源于卡码网(卡码网KamaCoder)
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】
【设计模式大纲】
【简介】
--什么是责任链模式(第21种设计模式)
责任链模式 是⼀种行为型设计模式 ,它允许你构建⼀个对象链,让请求从链的⼀端进⼊,然后沿着链上的对象依次处理,直到链上的某个对象能够处理该请求为止。
职责链上的处理者就是⼀个对象,可以对请求进⾏处理或者将请求转发给下⼀个节点,这个场景在⽣活中很常⻅,就是⼀个逐层向上递交的过程,最终的请求要么被处理者所处理,要么处理不了,这也因此可能导致请求⽆法被处理。
【组成结构】
责任链模式包括以下几个基本结构:
-
- 处理者Handler :定义⼀个处理请求的接⼝,包含⼀个处理请求的抽象⽅法和⼀个指向下⼀个处理者的链接。
-
- 具体处理者ConcreteHandler : 实现处理请求的⽅法,并判断能否处理请求,如果能够处理请求则进⾏处理,否则将请求传递给下⼀个处理者。
-
- 客户端:创建并组装处理者对象链,并将请求发送到链上的第⼀个处理者。
【简易实现 - Java】
以Java代码作以简要说明
1. 处理者
定义处理请求的接口
java
interface Handler {
// 处理请求的⽅法
void handleRequest(double amount);
// 设置下⼀个处理者的⽅法
void setNextHandler(Handler nextHandler);
}
2. 具体处理者
实现处理请求
java
class ConcreteHandler implements Handler {
private Handler nextHandler;
@Override
public void handleRequest(Request request) {
// 根据具体情况处理请求,如果⽆法处理则交给下⼀个处理者
if (canHandle(request)) {
// 处理请求的逻辑
} else if (nextHandler != null) {
// 交给下⼀个处理者处理
nextHandler.handleRequest(request);
} else {
// ⽆法处理请求的逻辑
}
}
@Override
public void setNextHandler(Handler nextHandler) {
this.nextHandler = nextHandler;
}
// 具体处理者⾃⼰的判断条件
private boolean canHandle(Request request) {
// 根据具体情况判断是否能够处理请求
return /* 判断条件 */;
}
}
3. 客户端
创建并组装处理者对象链,将请求发送给链上第⼀个处理者
java
public class Main {
public static void main(String[] args) {
// 创建处理者实例
Handler handler1 = new ConcreteHandler();
Handler handler2 = new ConcreteHandler();
// ...
// 构建责任链
handler1.setNextHandler(handler2);
// ...
// 发送请求
Request request = new Request(/* 请求参数 */);
handler1.handleRequest(request);
}
}
【使用场景】
责任链模式具有下⾯⼏个优点:
- 降低耦合度:将请求的发送者和接收者解耦,每个具体处理者都只负责处理与⾃⼰相关的请求,客户端不需要知道具体是哪个处理者处理请求。
- 增强灵活性:可以动态地添加或删除处理者,改变处理者之间的顺序以满⾜不同需求。
但是由于⼀个请求可能会经过多个处理者,这可能会导致⼀些性能问题 ,并且如果整个链上也没有合适的处理者来处理请求,就会导致请求⽆法被处理。
责任链模式是设计模式中简单且常⻅的设计模式,在⽇常中也会经常使⽤到,⽐如Java开发中过滤器的链式处理,以及Spring框架中的拦截器,都组装成⼀个处理链对请求、响应进⾏处理。
【C++编码部分】
1. 题目描述
小明所在的公司请假需要在OA系统上发布申请,整个请求流程包括多个处理者,每个处理者负责处理不同范围的请假天数,如果一个处理者不能处理请求,就会将请求传递给下一个处理者,请你实现责任链模式,可以根据请求天数找到对应的处理者。
审批责任链由主管(Supervisor), 经理(Manager)和董事(Director)组成,他们分别能够处理3天、7天和10天的请假天数。如果超过10天,则进行否决。
2. 输入描述
第一行是一个整数N(1 <= N <= 100), 表示请求申请的数量。接下来的N行,每行包括一个请求申请的信息,格式为"姓名 请假天数"。
3. 输出描述
对于每个请假请求,输出一行,表示该请求是否被批准。如果被批准/否决,输出被哪一个职级的人批准/否决。
4. C++编程示例(可直接运行)
java
/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file DutyChainMode.hpp
* @brief 责任链模式
* @autor 写代码的小恐龙er
* @date 2024/01/25
*/
#include <iostream>
#include <string>
using namespace std;
// 前置声明
// 用户请求类
class LeaveRequest;
// 处理者 接口类
class LeaveHandler;
// 具体处理者1 -- 主管(Supervisor) 3
class Supervisor;
// 具体处理者2 -- 经理(Manager) 7
class Manager;
// 具体处理者3 -- 董事(Director) 10
class Director;
// 具体定义
// 用户请求类
class LeaveRequest
{
//成员数据
private:
string _name;
int _daysLeave = 0;
// 成员函数
public:
//构造函数
LeaveRequest(string name, int days){
this->_name = name;
this->_daysLeave = days;
}
// 成员数据获取接口
string GetName(){
return this->_name;
}
int GetDaysLeave(){
return this->_daysLeave;
}
};
// 处理者 接口类
class LeaveHandler
{
// 接口
public:
virtual void HandleRequest(LeaveRequest *request) = 0;
};
// 具体处理者1 -- 主管(Supervisor) 3
class Supervisor : public LeaveHandler
{
//成员数据
private:
const int _maxDays = 3;
// 下一个处理者
LeaveHandler *_nextHandler;
// 接口函数重载
public:
// 构造函数
Supervisor(){}
Supervisor(LeaveHandler *nextHandler){
this->_nextHandler = nextHandler;
}
void HandleRequest(LeaveRequest *request) override {
if(request){
if(request->GetDaysLeave() <= _maxDays){
std::cout << request->GetName() << " Approved by Supervisor." << endl;
}
else if(_nextHandler){
_nextHandler->HandleRequest(request);
}
else std::cout << request->GetName() << " Denied by Supervisor." << endl;
}
}
};
// 具体处理者2 -- 经理(Manager) 7
class Manager : public LeaveHandler
{
//成员数据
private:
const int _maxDays = 7;
// 下一个处理者
LeaveHandler *_nextHandler;
// 接口函数重载
public:
// 构造函数
Manager(){}
Manager(LeaveHandler *nextHandler){
this->_nextHandler = nextHandler;
}
void HandleRequest(LeaveRequest *request) override {
if(request){
if(request->GetDaysLeave() <= _maxDays){
std::cout << request->GetName() << " Approved by Manager." << endl;
}
else if(_nextHandler){
_nextHandler->HandleRequest(request);
}
else std::cout << request->GetName() << " Denied by Manager." << endl;
}
}
};
// 具体处理者3 -- 董事(Director) 10
class Director : public LeaveHandler
{
//成员数据
private:
const int _maxDays = 10;
// 下一个处理者
const LeaveHandler *_nextHandler = nullptr;
// 接口函数重载
public:
// 构造函数
Director(){}
// Director(LeaveHandler *nextHandler){
// this->_nextHandler = nextHandler;
// }
void HandleRequest(LeaveRequest *request) override {
if(request){
if(request->GetDaysLeave() <= _maxDays){
std::cout << request->GetName() << " Approved by Director." << endl;
}
// else if(_nextHandler){
// _nextHandler->HandleRequest(request);
// }
else std::cout << request->GetName() << " Denied by Director." << endl;
}
}
};
int main()
{
// 请求数量
int requestNum = 0;
std::cin >> requestNum;
// 创建请求命令基类
LeaveRequest *request = nullptr;
// 创建处理者基类 -- 【创建处理流程时 也可单独创建一个类】
LeaveHandler *director = new Director();
LeaveHandler *manager = new Manager(director);
LeaveHandler *supervisor = new Supervisor(manager);
// 遍历
for(int i = 0; i < requestNum; i++){
// 请假者姓名 和 天数
string name = "";
int days = 0;
// 输入
std::cin >> name >> days;
// 新建请求类
request = new LeaveRequest(name, days);
// 开始处理请求
supervisor->HandleRequest(request);
}
//析构
delete director;
director = nullptr;
delete manager;
manager = nullptr;
delete supervisor;
supervisor = nullptr;
if(request != nullptr){
delete request;
request = nullptr;
}
return 0;
}
......
To be continued.