【设计模式】【行为型模式(Behavioral Patterns)】之责任链模式(Chain of Responsibility Pattern)

ops/2024/11/29 7:57:41/

1. 设计模式原理说明

责任链模式(Chain of Responsibility Pattern) 是一种行为设计模式,它允许你将请求沿着处理者链进行发送。每个处理者都可以处理请求,或者将其传递给链上的下一个处理者。这种模式使得多个对象都有机会处理请求,而无需提前指定具体的处理者。这样可以减少请求发送者和接收者之间的耦合。

主要角色
  1. Handler(抽象处理者):定义了一个处理请求的接口,通常包含一个后继连接,用于指向下一个处理者。
  2. ConcreteHandler(具体处理者):实现了处理请求的方法,判断是否处理该请求,如果不能处理则将请求转发给下一个处理者。
  3. Client(客户端):创建处理者对象并组织成一条链,向链中的第一个处理者提交请求。

2. UML 类图及解释

UML 类图
+-----------------+
|    Handler      |
|-----------------|
| - successor: Handler |
| - setSuccessor(successor: Handler) |
| - handleRequest(request: Request) |
+-----------------+^||v
+-----------------+
| ConcreteHandlerA|
|-----------------|
| - handleRequest(request: Request) |
+-----------------+^||v
+-----------------+
| ConcreteHandlerB|
|-----------------|
| - handleRequest(request: Request) |
+-----------------+
类图解释
  • Handler:定义了处理请求的接口,包含一个后继连接(successor),用于指向下一个处理者。
  • ConcreteHandlerA 和 ConcreteHandlerB:实现了处理请求的方法,判断是否处理该请求,如果不能处理则将请求转发给下一个处理者。
  • Client:创建处理者对象并组织成一条链,向链中的第一个处理者提交请求。

3. 代码案例及逻辑详解

Java 代码案例
// 抽象处理者
abstract class Handler {protected Handler successor;public void setSuccessor(Handler successor) {this.successor = successor;}public abstract void handleRequest(int request);
}// 具体处理者 A
class ConcreteHandlerA extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 0 && request < 10) {System.out.println("ConcreteHandlerA handled request " + request);} else if (successor != null) {successor.handleRequest(request);}}
}// 具体处理者 B
class ConcreteHandlerB extends Handler {@Overridepublic void handleRequest(int request) {if (request >= 10 && request < 20) {System.out.println("ConcreteHandlerB handled request " + request);} else if (successor != null) {successor.handleRequest(request);}}
}// 客户端
public class Client {public static void main(String[] args) {Handler handlerA = new ConcreteHandlerA();Handler handlerB = new ConcreteHandlerB();handlerA.setSuccessor(handlerB);handlerA.handleRequest(5);  // 应由 ConcreteHandlerA 处理handlerA.handleRequest(15); // 应由 ConcreteHandlerB 处理handlerA.handleRequest(25); // 没有处理者可以处理}
}
C++ 代码案例
#include <iostream>// 抽象处理者
class Handler {
protected:Handler* successor;
public:void setSuccessor(Handler* successor) {this->successor = successor;}virtual void handleRequest(int request) = 0;
};// 具体处理者 A
class ConcreteHandlerA : public Handler {
public:void handleRequest(int request) override {if (request >= 0 && request < 10) {std::cout << "ConcreteHandlerA handled request " << request << std::endl;} else if (successor != nullptr) {successor->handleRequest(request);}}
};// 具体处理者 B
class ConcreteHandlerB : public Handler {
public:void handleRequest(int request) override {if (request >= 10 && request < 20) {std::cout << "ConcreteHandlerB handled request " << request << std::endl;} else if (successor != nullptr) {successor->handleRequest(request);}}
};// 客户端
int main() {Handler* handlerA = new ConcreteHandlerA();Handler* handlerB = new ConcreteHandlerB();handlerA->setSuccessor(handlerB);handlerA->handleRequest(5);  // 应由 ConcreteHandlerA 处理handlerA->handleRequest(15); // 应由 ConcreteHandlerB 处理handlerA->handleRequest(25); // 没有处理者可以处理delete handlerA;delete handlerB;return 0;
}
Python 代码案例
# 抽象处理者
class Handler:def __init__(self):self.successor = Nonedef set_successor(self, successor):self.successor = successordef handle_request(self, request):pass# 具体处理者 A
class ConcreteHandlerA(Handler):def handle_request(self, request):if 0 <= request < 10:print(f"ConcreteHandlerA handled request {request}")elif self.successor is not None:self.successor.handle_request(request)# 具体处理者 B
class ConcreteHandlerB(Handler):def handle_request(self, request):if 10 <= request < 20:print(f"ConcreteHandlerB handled request {request}")elif self.successor is not None:self.successor.handle_request(request)# 客户端
if __name__ == "__main__":handlerA = ConcreteHandlerA()handlerB = ConcreteHandlerB()handlerA.set_successor(handlerB)handlerA.handle_request(5)  # 应由 ConcreteHandlerA 处理handlerA.handle_request(15) # 应由 ConcreteHandlerB 处理handlerA.handle_request(25) # 没有处理者可以处理
Go 代码案例
package mainimport ("fmt"
)// 抽象处理者
type Handler interface {setSuccessor(successor Handler)handleRequest(request int)
}// 具体处理者 A
type ConcreteHandlerA struct {successor Handler
}func (h *ConcreteHandlerA) setSuccessor(successor Handler) {h.successor = successor
}func (h *ConcreteHandlerA) handleRequest(request int) {if request >= 0 && request < 10 {fmt.Printf("ConcreteHandlerA handled request %d\n", request)} else if h.successor != nil {h.successor.handleRequest(request)}
}// 具体处理者 B
type ConcreteHandlerB struct {successor Handler
}func (h *ConcreteHandlerB) setSuccessor(successor Handler) {h.successor = successor
}func (h *ConcreteHandlerB) handleRequest(request int) {if request >= 10 && request < 20 {fmt.Printf("ConcreteHandlerB handled request %d\n", request)} else if h.successor != nil {h.successor.handleRequest(request)}
}// 客户端
func main() {handlerA := &ConcreteHandlerA{}handlerB := &ConcreteHandlerB{}handlerA.setSuccessor(handlerB)handlerA.handleRequest(5)  // 应由 ConcreteHandlerA 处理handlerA.handleRequest(15) // 应由 ConcreteHandlerB 处理handlerA.handleRequest(25) // 没有处理者可以处理
}

4. 总结

责任链模式 是一种行为设计模式,它允许你将请求沿着处理者链进行发送。每个处理者都可以处理请求,或者将其传递给链上的下一个处理者。这种模式使得多个对象都有机会处理请求,而无需提前指定具体的处理者。通过这种方式,可以减少请求发送者和接收者之间的耦合。

主要优点
  1. 解耦:请求的发送者和接收者之间没有直接的耦合关系,提高了系统的灵活性。
  2. 增强可扩展性:可以动态地增加或改变处理者的数量和顺序,而不会影响客户端。
  3. 支持多个处理者:多个处理者可以依次处理同一个请求,增加了系统的灵活性和可配置性。
主要缺点
  1. 调试困难:由于请求的处理过程是动态的,调试时可能难以跟踪请求的处理路径。
  2. 性能开销:如果链过长,可能会导致性能下降,尤其是在每个处理者都需要执行某些操作时。
适用场景
  • 当一个请求需要被多个对象中的一个或多个处理时。
  • 当处理者的选择需要在运行时动态决定时。
  • 当需要在不明确指定接收者的情况下,向多个对象中的一个发送请求时。
  • 当需要创建一个可灵活配置的处理流程时。

http://www.ppmy.cn/ops/137602.html

相关文章

【Unity】Unity编辑器扩展,替代预制体上重复拖拽赋值

今天做游戏时有个需求&#xff0c;游戏中需要给不同年份不同月份的奖牌制定不一样的非规则形状&#xff0c;其中形状为100个像素组成的不同图形&#xff0c;并且按照从1-100路径一个个解锁&#xff0c;所以需要全部手动放置。但是手动放置好后&#xff0c;发现再一个个挂到脚本…

英语知识在线学习:Spring Boot网站设计

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

数据库(MySQL黑马)

基础篇 MySQL概述 数据库概述 数据库相关概念 主流的关系型数据库管理系统 MySQL数据库的安装与启动 下载&#xff1a;MySQL :: MySQL Community Downloads 安装步骤 MySQL―8.0.40超详细保姆级安装教程_mysql8.0.40安装教程-CSDN博客文章浏览阅读1k次。_mysql8.0.40安装教…

深入浅出剖析典型文生图产品Midjourney

2022年7月,一个小团队推出了公测的 Midjourney,打破了 AIGC 领域的大厂垄断。作为一个精调生成模型,以聊天机器人方式部署在 Discord,它创作的《太空歌剧院》作品,甚至获得了美国「数字艺术/数码摄影」竞赛单元一等奖。 这一事件展示了 AI 在绘画领域惊人的创造力,让人们…

力扣刷题TOP101:4.BM5 合并k个已排序的链表

目录&#xff1a; 目的 思路 复杂度 记忆秘诀 python代码 目的 [{1,2},{1,4,5},{6}] 合并成 {1,1,2,4,5,6} 思路 这个任务是将 k 个升序链表合并成一个升序链表。假设有一个代跑腿小哥&#xff0c;他的任务是从多个快递点取包裹并统一派送。每个快递点的包裹已经按派送距…

MongoDB 中设置登录账号密码可以通过以下步骤实现

1. 启用身份验证 默认情况下&#xff0c;MongoDB 不启用身份验证&#xff0c;需要修改配置文件启用。 打开 MongoDB 配置文件&#xff08;通常是 mongod.conf&#xff09;。 确保配置中有以下行&#xff08;或添加&#xff09;&#xff1a; security:authorization: enabled…

六大排序算法:插入排序、希尔排序、选择排序、冒泡排序、堆排序、快速排序

本章讲述数据结构中的六大排序算法 欢迎大佬们踊跃讨论&#xff0c;感谢大家支持&#xff01; 我的博客主页链接 六大排序算法 一.插入排序1.1 直接插入排序1.2 希尔排序 二.选择排序2.1 单向选择排序2.2双向选择排序2.3 堆排序 三.交换排序3.1 冒泡排序3.2 快速排序3.2.1 Hoa…

登录服务器的密钥对是什么?

‌登录服务器的密钥对‌是指由一对密钥组成的安全凭证&#xff0c;包括一个公钥和一个私钥。公钥通常存储在服务器上&#xff0c;而私钥由用户保管。用户通过私钥加密数据&#xff0c;而公钥用于解密&#xff0c;确保只有拥有私钥的用户才能访问服务器。 密钥对的用途和安全性…