设计模式:责任链模式

目录

一、引言

二、模式定义与核心思想

三、责任链模式的纯与不纯

四、模式结构与组件

五、代码样例

六、优缺点分析

七、结语


一、引言

举个例子,小明是公司的一名员工,最近身体不舒服,需要请假一个月。他拿着请假条,先去找小组长签字。小组长签完字后,让他拿着请假条去找部门经理签字。部门经理签完字后,又让他拿着请假条去找总经理签字。直到总经理也签了字,小明的请假才算正式获批。

后来小明得知,请假天数在3天以内,直接找小组长签字即可,3~7天需要小组长和部门经理签字,超过7天需要小组长、部门经理和总经理签字。

所以,以上的处理过程,客户端代码的逻辑如下:

可以看到,在客户端是需要做出很多判断的。如果处理链条一改变,比如多了老板审批这一步的话,客户端是需要再加一个判断的。好的代码应该是高内聚低耦合的,也就是说,处理模块的改变不影响到客户端。追求的是小明一旦提交了请假申请,那么他只需要等待结果就好了,而不用跑去问这个哪个的。在这种场景下,应用责任链模式就很合适。

二、模式定义与核心思想

责任链模式的定义就是,避免将请求的发送者与接收者耦合,让多个对象都有机会处理请求。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

三、责任链模式的纯与不纯

经典的责任链模式为,当请求沿着处理链传递时,一旦有处理器可以对该请求进行处理,那么就不再继续往后传递。上面给出的定义就是经典责任链模式的定义,或者说是纯的责任链模式。与之对应的就是不纯的责任链模式。不纯的责任链模式就是,处理器可以处理请求的一部分,然后继续传递给下一个处理器。引言中请假的例子就是不纯的责任链模式。不管是纯与不纯,不论好坏,都有各自的应用场景,我们该关心的是这两种模式哪一种能更好的解决我们的问题。

四、模式结构与组件

责任链模式的结构和组件基本上是固定的,一个抽象的处理类,若干个具体处理类继承这个抽象的处理类,然后一个客户端发起请求。

五、代码样例

下面通过一个例子来说明:

需求:我们有一个文本处理的责任链,处理链中有两个处理器:

  1. 清除首尾空格处理器(TrimProcessor):清除文本首尾空格(部分处理),然后传递给下一个处理器。
  2. 大写处理器(UpperProcessor):将文本转为大写(另一种处理)。

处理过程: 输入: " hello world " 经过TrimProcessor:变成"hello world"(去除了首尾空格) 然后传递给UpperProcessor:变成"HELLO WORLD"。

cpp 复制代码
//chain.hpp
#ifndef chain_hpp
#define chain_hpp

#include <iostream>
#include <memory>
#include <string>
#include <algorithm>

class Request {
public:
    Request(std::string data) : _data(data) {}
    std::string getData() {
        return _data;
    }
    void setData(std::string &data) {
        _data = data;
    }
private:
    std::string _data;
};

class Processor {
public:
    Processor() : _next(nullptr) {}
    virtual void handleRequest(Request &request) = 0;
    void setNext(const std::shared_ptr<Processor> &next) {
        this->_next = next;
    }
protected:
    std::shared_ptr<Processor> _next;
};

class TrimProcessor : public Processor {
public:
    void handleRequest(Request &request) override {
        std::string data = request.getData();
        std::string result = trim(data);
        request.setData(result);
        if (_next) {
            _next->handleRequest(request);
        }
    }
private:
    std::string trim(const std::string &data) {
        size_t first = data.find_first_not_of(' ');
        if (first == std::string::npos) {
            return "";
        }
        size_t last = data.find_last_not_of(' ');
        return data.substr(first, last - first + 1);
    }
};

class UpperProcessor : public Processor {
public:
    void handleRequest(Request &request) override {
        std::string data = request.getData();
        std::string result = toUpperCase(data);
        request.setData(result);
    }
private:
    std::string toUpperCase(const std::string &data) {
        std::string result;
        for (auto &c : data) {
            result += toupper(c);
        }
        return result;
    }
};

#endif /* chain_hpp */

//main.cc
#include "chain.hpp"

int main()
{
    std::shared_ptr<Processor> chain = std::make_shared<TrimProcessor>();
    chain->setNext(std::make_shared<UpperProcessor>());
    Request request("     -hello world-  ");
    chain->handleRequest(request);
    std::cout << request.getData() << std::endl; // Output: HELLO WORLD
    return 0;
}

六、优缺点分析

优点:

  1. 将请求的发送者和处理者解耦。
  2. 可以灵活的增减处理器。
  3. 符合开闭原则。

缺点:

  1. 缺少尾处理器,有的请求可能无法处理------添加默认处理器兜底。
  2. 处理链过长,会影响到性能------控制处理链长度。
  3. 避免循环引用。

七、结语

责任链模式如同装配流水线,让请求在不同工位间流转处理。掌握这一设计模式,在遇到相应的场景时,可以迅速提升我们代码的逼格。


完~

相关推荐
Deschen10 小时前
设计模式-工厂模式
设计模式·简单工厂模式
阿无,10 小时前
Java设计模式之工厂模式
java·开发语言·设计模式
Camel卡蒙12 小时前
DDD架构——充血模型、领域模型
java·设计模式·架构
rongqing201912 小时前
Google 智能体设计模式:目标设定与监控
设计模式
weixin_4454766813 小时前
一天一个设计模式——开闭原则
服务器·设计模式·开闭原则
李广坤13 小时前
模板方法模式(Template Method Pattern)
设计模式
Asort19 小时前
JavaScript设计模式(十二)——代理模式 (Proxy)
前端·javascript·设计模式
简小瑞19 小时前
VSCode源码解密:Event<T> - 类型安全的事件系统
前端·设计模式·visual studio code
Mr_WangAndy20 小时前
C++设计模式_结构型模式_外观模式Facade
c++·设计模式·外观模式
李广坤20 小时前
策略模式(Strategy Pattern)
设计模式