前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++设计模式——Chain of Responsibility职责链模式

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

作者头像
Coder-ZZ
发布2024-07-25 11:10:18
540
发布2024-07-25 11:10:18
举报
文章被收录于专栏:C/C++进阶专栏

一,职责链模式的定义

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

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

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

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

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

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

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

二,职责链模式的结构

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

1.抽象处理器(Handler):

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

2.具体处理器(ConcreteHandler):

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

3.客户端(Client):

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

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

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

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

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

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

对应UML类图:

三,职责链模式代码样例

代码语言:javascript
复制
#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;
}

运行结果:

代码语言:javascript
复制
Handling request of type Type2.
Handling request of type Type3.
Unable to handle the request.

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

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

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

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

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

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

五,职责链模式的优缺点

职责链模式的优点:

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

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

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

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

职责链模式的缺点:

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

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

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

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

六,代码实战

Demo1:日志记录器

代码语言:javascript
复制
#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;
}

运行结果:

代码语言:javascript
复制
Error: This is a test message.
Debug: This is a test message.
Info: This is a test message.

Demo2:模拟消息接收

代码语言:javascript
复制
#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;
}

运行结果:

代码语言:javascript
复制
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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员与背包客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档