责任链模式

责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它允许多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。

为了更生动形象地理解责任链模式,我们可以通过一些日常生活中的例子来进行类比。

例子1:公司请假审批流程

场景描述

假设你在一家公司工作,你需要请假。公司的请假审批流程是逐级审批的:首先由你的直接主管审批,如果主管同意,则请假申请通过;如果主管不同意,则将申请转交给部门经理审批;如果部门经理也不同意,则转交给总经理审批。

责任链模式的应用
  • 请求:请假申请。
  • 处理者:各级审批人员(主管、部门经理、总经理)。
  • :审批流程链。

通过责任链模式,请假申请会沿着审批链逐级传递,直到有一个审批人员处理它为止。

类图表示
+----------------+       +----------------+       +----------------+
|   Handler      |       |   Supervisor   |       |   Manager      |
|----------------|       |----------------|       |----------------|
| + setNext()    |       | + handle()     |       | + handle()     |
| + handle()     |       +----------------+       +----------------+
+----------------+              ^                        ^
                                 |                        |
                                 |                        |
                                 +------------------------+
                                 |
                                 |
                         +----------------+
                         |   Director     |
                         |----------------|
                         | + handle()     |
                         +----------------+

代码示例:公司请假审批流程

#include <iostream>
#include <string>

// 抽象处理者:审批人员
class Handler {
protected:
    Handler* nextHandler;

public:
    Handler() : nextHandler(nullptr) {}

    void setNext(Handler* handler) {
        nextHandler = handler;
    }

    virtual void handle(int days) = 0;

    virtual ~Handler() = default;
};

// 具体处理者:主管
class Supervisor : public Handler {
public:
    void handle(int days) override {
        if (days <= 2) {
            std::cout << "Supervisor approved " << days << " days leave." << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(days);
        }
    }
};

// 具体处理者:部门经理
class Manager : public Handler {
public:
    void handle(int days) override {
        if (days <= 5) {
            std::cout << "Manager approved " << days << " days leave." << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(days);
        }
    }
};

// 具体处理者:总经理
class Director : public Handler {
public:
    void handle(int days) override {
        if (days <= 10) {
            std::cout << "Director approved " << days << " days leave." << std::endl;
        } else {
            std::cout << "Leave request for " << days << " days denied." << std::endl;
        }
    }
};

// 客户端代码
int main() {
    // 创建处理者
    Handler* supervisor = new Supervisor();
    Handler* manager = new Manager();
    Handler* director = new Director();

    // 设置责任链
    supervisor->setNext(manager);
    manager->setNext(director);

    // 发起请假请求
    int leaveDays = 3;
    supervisor->handle(leaveDays);

    leaveDays = 6;
    supervisor->handle(leaveDays);

    leaveDays = 11;
    supervisor->handle(leaveDays);

    // 清理内存
    delete supervisor;
    delete manager;
    delete director;

    return 0;
}

在这个示例中,Handler 类是抽象处理者,表示审批人员。SupervisorManagerDirector 类是具体处理者,它们实现了具体的审批行为。通过责任链模式,请假申请会沿着审批链逐级传递,直到有一个审批人员处理它为止。

例子2:技术支持服务台

场景描述

假设你在一家技术支持服务台工作,客户打电话来报告问题。服务台有不同级别的技术支持人员:一线支持、二线支持和专家支持。客户的问题会首先由一线支持处理,如果一线支持无法解决,则转交给二

好的,我们继续完成技术支持服务台的例子。

例子2:技术支持服务台(续)

场景描述(续)

客户的问题会首先由一线支持处理,如果一线支持无法解决,则转交给二线支持;如果二线支持也无法解决,则转交给专家支持。

责任链模式的应用
  • 请求:客户的问题。
  • 处理者:各级技术支持人员(一线支持、二线支持、专家支持)。
  • :技术支持流程链。

通过责任链模式,客户的问题会沿着技术支持链逐级传递,直到有一个技术支持人员处理它为止。

类图表示
+----------------+       +----------------+       +----------------+
|   Handler      |       |   FirstLevel   |       |   SecondLevel  |
|----------------|       |----------------|       |----------------|
| + setNext()    |       | + handle()     |       | + handle()     |
| + handle()     |       +----------------+       +----------------+
+----------------+              ^                        ^
                                 |                        |
                                 |                        |
                                 +------------------------+
                                 |
                                 |
                         +----------------+
                         |   ExpertLevel  |
                         |----------------|
                         | + handle()     |
                         +----------------+

代码示例:技术支持服务台

#include <iostream>
#include <string>

// 抽象处理者:技术支持人员
class Handler {
protected:
    Handler* nextHandler;

public:
    Handler() : nextHandler(nullptr) {}

    void setNext(Handler* handler) {
        nextHandler = handler;
    }

    virtual void handle(const std::string& issue) = 0;

    virtual ~Handler() = default;
};

// 具体处理者:一线支持
class FirstLevelSupport : public Handler {
public:
    void handle(const std::string& issue) override {
        if (issue == "simple issue") {
            std::cout << "First Level Support resolved the issue: " << issue << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(issue);
        }
    }
};

// 具体处理者:二线支持
class SecondLevelSupport : public Handler {
public:
    void handle(const std::string& issue) override {
        if (issue == "intermediate issue") {
            std::cout << "Second Level Support resolved the issue: " << issue << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(issue);
        }
    }
};

// 具体处理者:专家支持
class ExpertLevelSupport : public Handler {
public:
    void handle(const std::string& issue) override {
        if (issue == "complex issue") {
            std::cout << "Expert Level Support resolved the issue: " << issue << std::endl;
        } else {
            std::cout << "Issue: " << issue << " could not be resolved." << std::endl;
        }
    }
};

// 客户端代码
int main() {
    // 创建处理者
    Handler* firstLevel = new FirstLevelSupport();
    Handler* secondLevel = new SecondLevelSupport();
    Handler* expertLevel = new ExpertLevelSupport();

    // 设置责任链
    firstLevel->setNext(secondLevel);
    secondLevel->setNext(expertLevel);

    // 发起问题请求
    std::string issue = "simple issue";
    firstLevel->handle(issue);

    issue = "intermediate issue";
    firstLevel->handle(issue);

    issue = "complex issue";
    firstLevel->handle(issue);

    issue = "unknown issue";
    firstLevel->handle(issue);

    // 清理内存
    delete firstLevel;
    delete secondLevel;
    delete expertLevel;

    return 0;
}

在这个示例中,Handler 类是抽象处理者,表示技术支持人员。FirstLevelSupportSecondLevelSupportExpertLevelSupport 类是具体处理者,它们实现了具体的技术支持行为。通过责任链模式,客户的问题会沿着技术支持链逐级传递,直到有一个技术支持人员处理它为止。

总结

责任链模式的核心思想是将请求沿着一条链传递,直到有一个对象处理它为止。通过责任链模式,可以避免请求的发送者和接收者之间的耦合,使得系统更加灵活和可扩展。

责任链模式的优点
  1. 降低耦合度:请求的发送者和接收者解耦,发送者无需知道具体的接收者。
    好的,我们继续总结责任链模式的优点和缺点,并探讨其应用场景。

责任链模式的优点(续)

  1. 增强灵活性:可以动态地添加或删除处理者,改变处理者的顺序,灵活地调整责任链。
  2. 职责分离:每个处理者只需关注自己能处理的请求,职责单一,符合单一职责原则。

责任链模式的缺点

  1. 性能问题:如果责任链过长,可能会导致请求的处理时间变长,影响系统性能。
  2. 调试困难:由于请求沿着链传递,可能会导致调试和排查问题变得更加困难,尤其是在链条较长时。
  3. 不保证请求被处理:如果没有处理者能够处理请求,可能会导致请求未被处理的情况,需要额外的机制来处理这种情况。

责任链模式的应用场景

责任链模式适用于以下场景:

  1. 多个对象可以处理同一请求:例如,多个审批人员可以处理同一个请假申请,多个技术支持人员可以处理同一个客户问题。
  2. 动态指定处理者:处理者的顺序和数量可以动态变化,例如,审批流程可以根据不同的请假天数动态调整审批人员。
  3. 需要解耦请求的发送者和接收者:例如,客户问题的报告者和技术支持人员之间需要解耦,发送者无需知道具体的接收者。

例子3:日志记录系统

场景描述

假设你在开发一个日志记录系统,系统需要根据日志的严重程度(如信息、警告、错误)将日志记录到不同的地方(如控制台、文件、数据库)。日志记录系统需要能够灵活地扩展和调整日志处理的顺序。

责任链模式的应用
  • 请求:日志记录请求。
  • 处理者:不同的日志处理器(控制台处理器、文件处理器、数据库处理器)。
  • :日志处理链。

通过责任链模式,日志记录请求会沿着日志处理链逐级传递,直到有一个日志处理器处理它为止。

类图表示
+----------------+       +----------------+       +----------------+
|   Handler      |       | ConsoleHandler |       |  FileHandler   |
|----------------|       |----------------|       |----------------|
| + setNext()    |       | + handle()     |       | + handle()     |
| + handle()     |       +----------------+       +----------------+
+----------------+              ^                        ^
                                 |                        |
                                 |                        |
                                 +------------------------+
                                 |
                                 |
                         +----------------+
                         | DatabaseHandler|
                         |----------------|
                         | + handle()     |
                         +----------------+

代码示例:日志记录系统

#include <iostream>
#include <string>

// 抽象处理者:日志处理器
class Handler {
protected:
    Handler* nextHandler;

public:
    Handler() : nextHandler(nullptr) {}

    void setNext(Handler* handler) {
        nextHandler = handler;
    }

    virtual void handle(const std::string& log, const std::string& level) = 0;

    virtual ~Handler() = default;
};

// 具体处理者:控制台处理器
class ConsoleHandler : public Handler {
public:
    void handle(const std::string& log, const std::string& level) override {
        if (level == "INFO") {
            std::cout << "Console: " << log << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(log, level);
        }
    }
};

// 具体处理者:文件处理器
class FileHandler : public Handler {
public:
    void handle(const std::string& log, const std::string& level) override {
        if (level == "WARNING") {
            std::cout << "File: " << log << std::endl;
        } else if (nextHandler) {
            nextHandler->handle(log, level);
        }
    }
};

// 具体处理者:数据库处理器
class DatabaseHandler : public Handler {
public:
    void handle(const std::string& log, const std::string& level) override {
        if (level == "ERROR") {
            std::cout << "Database: " << log << std::endl;
        } else {
            std::cout << "Unhandled log level: " << level << std::endl;
        }
    }
};

好的,我们继续完成日志记录系统的代码示例。

### 代码示例:日志记录系统(续)

```cpp
int main() {
    // 创建处理者
    Handler* consoleHandler = new ConsoleHandler();
    Handler* fileHandler = new FileHandler();
    Handler* databaseHandler = new DatabaseHandler();

    // 设置责任链
    consoleHandler->setNext(fileHandler);
    fileHandler->setNext(databaseHandler);

    // 发起日志记录请求
    std::string log = "This is an informational message.";
    std::string level = "INFO";
    consoleHandler->handle(log, level);

    log = "This is a warning message.";
    level = "WARNING";
    consoleHandler->handle(log, level);

    log = "This is an error message.";
    level = "ERROR";
    consoleHandler->handle(log, level);

    log = "This is an unknown level message.";
    level = "UNKNOWN";
    consoleHandler->handle(log, level);

    // 清理内存
    delete consoleHandler;
    delete fileHandler;
    delete databaseHandler;

    return 0;
}

在这个示例中,Handler 类是抽象处理者,表示日志处理器。ConsoleHandlerFileHandlerDatabaseHandler 类是具体处理者,它们实现了具体的日志处理行为。通过责任链模式,日志记录请求会沿着日志处理链逐级传递,直到有一个日志处理器处理它为止。

总结

责任链模式是一种非常有用的设计模式,适用于需要多个对象处理同一请求的场景。通过责任链模式,可以降低请求的发送者和接收者之间的耦合度,增强系统的灵活性和可扩展性。

责任链模式的优点
  1. 降低耦合度:请求的发送者和接收者解耦,发送者无需知道具体的接收者。
  2. 增强灵活性:可以动态地添加或删除处理者,改变处理者的顺序,灵活地调整责任链。
  3. 职责分离:每个处理者只需关注自己能处理的请求,职责单一,符合单一职责原则。
责任链模式的缺点
  1. 性能问题:如果责任链过长,可能会导致请求的处理时间变长,影响系统性能。
  2. 调试困难:由于请求沿着链传递,可能会导致调试和排查问题变得更加困难,尤其是在链条较长时。
  3. 不保证请求被处理:如果没有处理者能够处理请求,可能会导致请求未被处理的情况,需要额外的机制来处理这种情况。
责任链模式的应用场景
  1. 多个对象可以处理同一请求:例如,多个审批人员可以处理同一个请假申请,多个技术支持人员可以处理同一个客户问题。
  2. 动态指定处理者:处理者的顺序和数量可以动态变化,例如,审批流程可以根据不同的请假天数动态调整审批人员。
  3. 需要解耦请求的发送者和接收者:例如,客户问题的报告者和技术支持人员之间需要解耦,发送者无需知道具体的接收者。

通过这些例子和总结,希望你能更生动形象地理解责任链模式,并在实际开发中灵活应用这一设计模式。

  • 9
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛掰是怎么形成的

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值