程序员与背包客_CoderZ

程序员与背包客_CoderZ

一,职责链模式的定义

职责链模式,又被称为责任链模式,是一种行为型设计模式,它让多个对象依次处理收到的请求,直到处理完成为止。

职责链模式需要使用多个对象,其中的每个对象要么处理请求,要么将请求传递给下一个对象,该模式因此可以实现发送方与接收方的松散耦合。

在职责链模式中,一个对象可以被理解为处理器,每个处理器都包含对下一个处理器的引用,多个对象之间形成了一个链表的结构。

职责链模式在现实生活中的抽象实例:

审批流程:在流程中,当一个申请需要多级审批时,可以使用职责链模式。每一级审批者都是职责链的一部分。

银行账户验证:在银行系统中,需要对用户进行身份验证和授权操作,而验证操作涉及多个步骤。

异常处理:在程序开发中,每个异常处理器可以处理特定类型的异常,如果当前处理器无法解决,则传递给下一个处理器。

二,职责链模式的结构

职责链模式主要包含以下组件:

1.抽象处理器(Handler):

处理器的抽象类,声明处理请求的抽象接口,并持有对下一个处理器的引用。

2.具体处理器(ConcreteHandler):

继承自抽象处理器,包含了对处理请求接口的具体实现,负责处理特定类型的请求或将请求传递给下一个处理器。

3.客户端(Client):

负责创建处理器的实例,并将它们加入到职责链中。然后向第一个处理器发送请求,并等待职责链的返回结果。

组件之间的工作步骤如下:

1.客户端将请求传递给职责链中的第一个处理器。

2.第一个处理器尝试处理请求。如果处理成功,则结束处理过程并返回结果,如果无法处理,则将请求转发给下一个处理器。

3.下一个处理器重复步骤2,直到找到能够处理请求的处理器,或者职责链中没有更多的处理器。

4.客户端获得处理结果。

对应UML类图:

C++设计模式——Chain of Responsibility职责链模式-LMLPHP

三,职责链模式代码样例

#include <iostream>
#include <string>
class Handler
{
protected:
       Handler* successor;
public:
       void setSuccessor(Handler* successor)
       {
              this->successor = successor;
       }
       virtual void handleRequest(const std::string& request) = 0;
};
class ConcreteHandler1 : public Handler
{
public:
       void handleRequest(const std::string& request) override
       {
              if (request == "Type1")
              {
                      std::cout << "Handling request of type Type1." << std::endl;
              }
              else if (successor != nullptr)
              {
                      successor->handleRequest(request);
              }
              else
              {
                      std::cout << "Unable to handle the request." << std::endl;
              }
       }
};
class ConcreteHandler2 : public Handler
{
public:
       void handleRequest(const std::string& request) override
       {
              if (request == "Type2")
              {
                      std::cout << "Handling request of type Type2." << std::endl;
              }
              else if (successor != nullptr)
              {
                      successor->handleRequest(request);
              }
              else
              {
                      std::cout << "Unable to handle the request." << std::endl;
              }
       }
};
class ConcreteHandler3 : public Handler
{
public:
       void handleRequest(const std::string& request) override
       {
              if (request == "Type3")
              {
                      std::cout << "Handling request of type Type3." << std::endl;
              }
              else if (successor != nullptr)
              {
                      successor->handleRequest(request);
              }
              else
              {
                      std::cout << "Unable to handle the request." << std::endl;
              }
       }
};
int main()
{
       Handler* handler1 = new ConcreteHandler1();
       Handler* handler2 = new ConcreteHandler2();
       Handler* handler3 = new ConcreteHandler3();
       handler1->setSuccessor(handler2);
       handler2->setSuccessor(handler3);
       handler1->handleRequest("Type2");
       handler1->handleRequest("Type3");
       handler1->handleRequest("Type4");
       delete handler1;
       delete handler2;
       delete handler3;
       return 0;
}

运行结果:

Handling request of type Type2.
Handling request of type Type3.
Unable to handle the request.

四,职责链模式的应用场景

命令处理器:比如在游戏或GUI应用中,用户可以发送各种操作命令,如“播放音乐”、“关闭窗口”,而具体执行过程由一系列处理器完成。

日志记录器:将不同严重等级的日志交给不同的处理器去打印。

Web服务开发:在Web服务中,对请求进行校验和过滤,如权限验证、数据校验等。

权限控制:在用户权限管理中,可以根据角色的不同职责分配不同的权限验证步骤。

消息路由:在网络通信中,将不同类型的消息分别发送给不同的处理程序。

五,职责链模式的优缺点

职责链模式的优点:

和命令模式类似,可以实现发送者和接收者的解耦。

灵活性强,可以修改职责链中的结构和顺序。

有扩展性,可以在最小改动的情况下添加新的处理器。

处理器可以在不同的职责链中重复使用。

职责链模式的缺点:

对请求的处理可能覆盖不全,导致bug的产生。

请求的处理过程十分冗长。

请求的传递涉及多个对象,性能开销大。

责任链需要被一直维护和管理。

六,代码实战

Demo1:日志记录器

#include <iostream>
#include <string>
#include <vector>
//Logger接口
class Logger {
public:
    virtual void log(const std::string& message) = 0;
};
//处理正常日志
class InfoLogger: public Logger{
public:
    void log(const std::string& message) override {
        std::cerr << "Info: " << message << std::endl;
    }
};
//处理调试日志
class DebugLogger: public Logger{
public:
    void log(const std::string& message) override {
        std::cout << "Debug: " << message << std::endl;
    }
};
//处理错误日志
class ErrorLogger: public Logger{
public:
    void log(const std::string& message) override {
        std::cerr << "Error: " << message << std::endl;
    }
};
class LoggingChain {
private:
    std::vector<std::shared_ptr<Logger>> loggers;
public:
    void addLogger(std::shared_ptr<Logger> logger) {
        loggers.push_back(logger);
    }
    void log(const std::string& message) {
        for (auto it = loggers.rbegin(); it != loggers.rend(); ++it) {
            (*it)->log(message);
        }
    }
};
int main() {
    LoggingChain chain;
    chain.addLogger(std::make_shared<InfoLogger>());
    chain.addLogger(std::make_shared<DebugLogger>());
    chain.addLogger(std::make_shared<ErrorLogger>());
    chain.log("This is a test message.");
    return 0;
}

运行结果:

Error: This is a test message.
Debug: This is a test message.
Info: This is a test message.

Demo2:模拟消息接收

#include <iostream>
#include <string>
#include <vector>
class Message {
public:
    virtual ~Message() {}
};
class TextMessage : public Message {
};
class ImageMessage : public Message {
};
class MessageHandler{
public:
    virtual void handle(Message* msg) = 0;
};
class TextProcessor: public MessageHandler{
public:
    void handle(Message* msg) override{
        if (dynamic_cast<TextMessage*>(msg)) {
            std::cout << "handling a text message." << std::endl;
            process(*static_cast<TextMessage*>(msg));
        }
        else {
            forward(msg);
        }
    }
private:
    void process(TextMessage& msg) {
    }
    void forward(Message* msg) {
    }
};
class ImageProcessor: public MessageHandler{
public:
    void handle(Message* msg) override {
        if (dynamic_cast<ImageMessage*>(msg)) {
            std::cout << "handling an image message." << std::endl;
            process(*static_cast<ImageMessage*>(msg));
        }
        else {
            forward(msg);
        }
    }
private:
    void process(ImageMessage& img){
    }
    void forward(Message* msg){
    }
};
class ChainOfResponsibility {
public:
    void setHandler(MessageHandler* handler){
        current_ = handler;
    }
    void handle(Message* msg) {
        current_->handle(msg);
    }
private:
    MessageHandler* current_ = nullptr;
};
int main() {
    ChainOfResponsibility chain;
    TextProcessor txtProc;
    ImageProcessor imgProc;
    chain.setHandler(&txtProc);
    chain.handle(new TextMessage());
    chain.setHandler(&imgProc);
    chain.handle(new ImageMessage());
    return 0;
}

运行结果:

handling a text message.
handling an image message.

七,参考阅读

https://www.geeksforgeeks.org/chain-responsibility-design-pattern/

https://www.tutorialspoint.com/design_pattern/chain_of_responsibility_pattern.htm

https://sourcemaking.com/design_patterns/chain_of_responsibility

09-05 08:04