C++ 设计模式之责任链模式

【声明】本题目来源于卡码网(卡码网KamaCoder
【提示:如果不想看文字介绍,可以直接跳转到C++编码部分


设计模式大纲】

【简介】

--什么是责任链模式(第21种设计模式)

责任链模式 是⼀种行为型设计模式 ,它允许你构建⼀个对象链,让请求从链的⼀端进⼊,然后沿着链上的对象依次处理,直到链上的某个对象能够处理该请求为止。

职责链上的处理者就是⼀个对象,可以对请求进⾏处理或者将请求转发给下⼀个节点,这个场景在⽣活中很常⻅,就是⼀个逐层向上递交的过程,最终的请求要么被处理者所处理,要么处理不了,这也因此可能导致请求⽆法被处理。


【组成结构】

责任链模式包括以下几个基本结构:

    1. 处理者Handler :定义⼀个处理请求的接⼝,包含⼀个处理请求的抽象⽅法和⼀个指向下⼀个处理者的链接。
    1. 具体处理者ConcreteHandler : 实现处理请求的⽅法,并判断能否处理请求,如果能够处理请求则进⾏处理,否则将请求传递给下⼀个处理者。
    1. 客户端:创建并组装处理者对象链,并将请求发送到链上的第⼀个处理者

【简易实现 - 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.

相关推荐
南东山人38 分钟前
一文说清:C和C++混合编程
c语言·c++
吾日三省吾码1 小时前
JVM 性能调优
java
弗拉唐2 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
oi773 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
少说多做3433 小时前
Android 不同情况下使用 runOnUiThread
android·java
知兀3 小时前
Java的方法、基本和引用数据类型
java·笔记·黑马程序员
蓝黑20203 小时前
IntelliJ IDEA常用快捷键
java·ide·intellij-idea
Ysjt | 深3 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++