当前位置: 首页 > ai >正文

设计模式(九)

职责链模式(Chain of Responsibility)详解

一、核心概念

职责链模式将请求的发送者和接收者解耦,使多个对象都有机会处理请求。这些对象连接成一条链,请求沿着链传递,直到有一个对象处理它为止。该模式允许动态调整处理者的顺序或组合,增强系统灵活性。

核心组件

  1. 抽象处理者(Handler):定义处理请求的接口,包含对下一个处理者的引用。
  2. 具体处理者(Concrete Handler):实现处理请求的方法,决定是否处理请求或将其传递给下一个处理者。
  3. 客户端(Client):将请求发送到链的起始处理者。
二、代码示例:员工请假审批系统

场景:员工请假需要不同层级的领导审批(组长→经理→总监),根据请假天数自动选择审批者。

#include <iostream>
#include <memory>// 请假请求
class LeaveRequest {
private:int days;std::string name;public:LeaveRequest(const std::string& name, int days) : name(name), days(days) {}int getDays() const { return days; }std::string getName() const { return name; }
};// 抽象处理者:领导
class Leader {
protected:std::shared_ptr<Leader> nextLeader;  // 指向下一个处理者public:virtual void setNextLeader(std::shared_ptr<Leader> leader) {nextLeader = leader;}virtual void handleRequest(const LeaveRequest& request) = 0;virtual ~Leader() = default;
};// 具体处理者:组长
class TeamLeader : public Leader {
public:void handleRequest(const LeaveRequest& request) override {if (request.getDays() <= 3) {std::cout << "组长批准" << request.getName() << "请假" << request.getDays() << "天" << std::endl;} else if (nextLeader) {std::cout << "组长无法处理,转交上级..." << std::endl;nextLeader->handleRequest(request);} else {std::cout << "请假天数过长,无人处理" << std::endl;}}
};// 具体处理者:经理
class Manager : public Leader {
public:void handleRequest(const LeaveRequest& request) override {if (request.getDays() <= 7) {std::cout << "经理批准" << request.getName() << "请假" << request.getDays() << "天" << std::endl;} else if (nextLeader) {std::cout << "经理无法处理,转交上级..." << std::endl;nextLeader->handleRequest(request);} else {std::cout << "请假天数过长,无人处理" << std::endl;}}
};// 具体处理者:总监
class Director : public Leader {
public:void handleRequest(const LeaveRequest& request) override {if (request.getDays() <= 15) {std::cout << "总监批准" << request.getName() << "请假" << request.getDays() << "天" << std::endl;} else {std::cout << "请假天数超过15天,拒绝批准" << std::endl;}}
};// 客户端代码
int main() {// 创建处理者auto teamLeader = std::make_shared<TeamLeader>();auto manager = std::make_shared<Manager>();auto director = std::make_shared<Director>();// 构建责任链teamLeader->setNextLeader(manager);manager->setNextLeader(director);// 提交请假请求LeaveRequest request1("张三", 2);teamLeader->handleRequest(request1);LeaveRequest request2("李四", 5);teamLeader->handleRequest(request2);LeaveRequest request3("王五", 10);teamLeader->handleRequest(request3);LeaveRequest request4("赵六", 20);teamLeader->handleRequest(request4);return 0;
}
三、职责链模式的优势
  1. 解耦发送者和接收者

    • 请求者无需知道哪个对象处理请求,只需将请求发送到链上。
  2. 动态组合处理者

    • 可在运行时动态调整处理者的顺序或组成。
  3. 简化对象职责

    • 每个处理者只需关注自己的职责,无需关心整条链的结构。
  4. 增强可扩展性

    • 新增处理者只需实现接口并加入链中,无需修改现有代码。
四、实现变种
  1. 纯职责链 vs 不纯职责链

    • 纯职责链:每个处理者要么处理请求,要么完全不处理(如示例)。
    • 不纯职责链:处理者可部分处理请求后继续传递(如日志过滤)。
  2. 动态链构建

    • 通过配置文件或工厂动态构建责任链,适应不同场景。
  3. 并行链处理

    • 多个处理者同时处理请求,返回首个成功的结果(如负载均衡)。
五、适用场景
  1. 多级审批系统

    • 如请假、报销等流程,根据金额或权限自动分配审批人。
  2. 事件处理系统

    • 如GUI事件传递(按钮点击→容器→窗口)。
  3. 日志过滤系统

    • 根据日志级别(INFO→WARN→ERROR)选择处理方式。
  4. 请求拦截器

    • 如Web应用中的过滤器链(身份验证→日志记录→权限检查)。
六、注意事项
  1. 链的完整性

    • 确保链的末端有默认处理者,避免请求无人处理。
  2. 性能问题

    • 过长的链可能影响性能,需控制链的长度。
  3. 调试难度

    • 链的动态性可能导致调试困难,需添加适当的日志。
  4. 与状态模式的区别

    • 职责链模式中处理者可自由决定是否传递请求;状态模式中状态转移由上下文控制。

职责链模式通过将请求处理者组织成链,实现了请求发送者与接收者的解耦,使系统更具灵活性和可维护性。在需要动态处理请求或多级处理的场景中,该模式尤为适用。

中介者模式(Mediator Pattern)详解

一、核心概念

中介者模式通过一个中介对象来封装一系列对象间的交互,使各对象无需显式引用彼此,从而降低耦合度。中介者负责协调对象间的通信,所有交互都通过中介者进行,而非对象直接调用。

核心组件

  1. 抽象中介者(Mediator):定义协调对象交互的接口。
  2. 具体中介者(Concrete Mediator):实现中介者接口,维护对象引用并处理交互逻辑。
  3. 抽象同事类(Colleague):定义同事对象的公共接口,持有中介者引用。
  4. 具体同事类(Concrete Colleague):实现抽象同事类,通过中介者与其他同事通信。

没有使用中介模式前是网状结构,关系混乱

现在改为辐射状,变为多对一

二、代码示例:机场塔台调度系统

场景:飞机降落和起飞需要塔台协调,避免跑道冲突。飞机(同事)不直接通信,而是通过塔台(中介者)调度。

#include <iostream>
#include <string>
#include <memory>
#include <vector>// 前向声明
class Tower;// 抽象同事类:飞机
class Aircraft {
protected:Tower* tower;std::string flightNumber;public:Aircraft(Tower* tower, const std::string& flightNumber) : tower(tower), flightNumber(flightNumber) {}virtual void requestLanding() = 0;virtual void confirmLanding() = 0;virtual std::string getFlightNumber() const = 0;virtual ~Aircraft() = default;
};// 抽象中介者:塔台
class Tower {
public:virtual void registerAircraft(Aircraft* aircraft) = 0;virtual void handleLandingRequest(Aircraft* aircraft) = 0;virtual void clearRunway() = 0;virtual ~Tower() = default;
};// 具体同事类:客机
class PassengerAircraft : public Aircraft {
public:using Aircraft::Aircraft;  // 继承构造函数void requestLanding() override {std::cout << "[" << flightNumber << "] 请求降落" << std::endl;tower->handleLandingRequest(this);}void confirmLanding() override {std::cout << "[" << flightNumber << "] 确认降落,跑道清空" << std::endl;}std::string getFlightNumber() const override { return flightNumber; }
};// 具体同事类:货机
class CargoAircraft : public Aircraft {
public:using Aircraft::Aircraft;  // 继承构造函数void requestLanding() override {std::cout << "[" << flightNumber << "] 请求降落" << std::endl;tower->handleLandingRequest(this);}void confirmLanding() override {std::cout << "[" << flightNumber << "] 确认降落,跑道清空" << std::endl;}std::string getFlightNumber() const override { return flightNumber; }
};// 具体中介者:控制塔台
class ControlTower : public Tower {
private:std::vector<Aircraft*> aircrafts;bool runwayAvailable = true;public:void registerAircraft(Aircraft* aircraft) override {aircrafts.push_back(aircraft);std::cout << "塔台已注册航班: " << aircraft->getFlightNumber() << std::endl;}void handleLandingRequest(Aircraft* aircraft) override {if (runwayAvailable) {runwayAvailable = false;std::cout << "塔台: 跑道可用," << aircraft->getFlightNumber() << " 可以降落" << std::endl;aircraft->confirmLanding();} else {std::cout << "塔台: 跑道繁忙," << aircraft->getFlightNumber() << " 请等待" << std::endl;}}void clearRunway() override {runwayAvailable = true;std::cout << "塔台: 跑道已清空,可以接受新降落请求" << std::endl;}
};// 客户端代码
int main() {auto tower = std::make_unique<ControlTower>();auto plane1 = std::make_unique<PassengerAircraft>(tower.get(), "CA1234");auto plane2 = std::make_unique<CargoAircraft>(tower.get(), "CZ5678");auto plane3 = std::make_unique<PassengerAircraft>(tower.get(), "MU9012");tower->registerAircraft(plane1.get());tower->registerAircraft(plane2.get());tower->registerAircraft(plane3.get());// 模拟多个飞机同时请求降落plane1->requestLanding();plane2->requestLanding();plane3->requestLanding();// 跑道清空后再次请求tower->clearRunway();plane2->requestLanding();return 0;
}
三、中介者模式的优势
  1. 降低耦合度

    • 对象间无需直接引用,所有交互通过中介者,减少依赖。
  2. 集中控制交互

    • 中介者作为交互中心,便于统一管理和修改交互逻辑。
  3. 增强可扩展性

    • 新增同事或修改交互逻辑只需调整中介者,无需修改所有同事类。
  4. 简化对象设计

    • 同事类只需关注自身业务逻辑,无需处理复杂的交互关系。
四、实现变种
  1. 事件总线(Event Bus)

    • 中介者维护事件队列,同事通过发布/订阅机制通信(如Guava EventBus)。
  2. MVC模式中的Controller

    • Controller作为View和Model的中介者,处理两者间的交互。
  3. 分布式系统中的消息队列

    • 如RabbitMQ、Kafka作为服务间的中介者,实现解耦通信。
五、适用场景
  1. 对象间交互复杂

    • 如GUI组件间的交互(按钮、文本框、下拉菜单)。
  2. 网状结构转星型结构

    • 将多对多关系转化为一对多关系,如社交网络中的好友关系。
  3. 系统模块间松耦合

    • 如电商系统中订单、库存、支付模块的交互。
  4. 需要集中控制的场景

    • 如多人游戏中的房间管理、交通调度系统。
六、注意事项
  1. 中介者复杂度

    • 中介者可能变得过于庞大,需合理拆分功能或采用分层中介者。
  2. 单点故障风险

    • 中介者作为核心组件,若出现故障可能影响整个系统。
  3. 性能开销

    • 所有交互通过中介者中转,可能引入性能瓶颈。
  4. 与观察者模式的区别

    • 中介者模式中同事对象依赖中介者;观察者模式中观察者与被观察对象松耦合。

中介者模式通过引入中介对象,将复杂的对象间交互集中管理,降低了系统耦合度,提高了可维护性。在需要控制对象间直接通信的场景中,该模式尤为有效。

http://www.xdnf.cn/news/14777.html

相关文章:

  • {{ }}和v-on:click
  • 两级缓存 Caffeine + Redis 架构:原理、实现与实践
  • Bean属性转换框架深度对比:从BeanUtils到MapStruct的演进之路
  • 【AI News | 20250702】每日AI进展
  • 修改阿里云vps为自定义用户登录
  • 大数据救公益:数字时代下的社会力量如何玩转“数据+善意”
  • 项目——视频共享系统测试
  • Element UI 完整使用实战示例
  • 【Python】图像识别的常用功能函数
  • c++ 的标准库 --- std::
  • 使用numpy的快速傅里叶变换的一些问题
  • x86汇编语言入门基础(三)汇编指令篇1 逻辑位运算
  • 6. 常见K线形态(楔形与旗形)
  • docker 介绍
  • redis缓存三大问题分析与解决方案
  • 在银河麒麟V10 SP1上手动安装与配置高版本Docker的完整指南
  • 归并排序详解
  • 【网工|知识升华版|实验】4 DHCP原理及应用
  • 数据结构20250620_数据结构考试
  • 南方大暴雨及洪水数据分析与可视化
  • 【Linux】不小心又创建了一个root权限账户,怎么将它删除?!
  • Rust实现FasterR-CNN目标检测全流程
  • 什么是端到端自动驾驶
  • [HDLBits] Cs450/timer
  • Spring MVC详解
  • windows系统下将Docker Desktop安装到除了C盘的其它盘中
  • 力扣 hot100 Day32
  • 毫米波雷达 – 深度学习
  • 腾讯 iOA 零信任产品:安全远程访问的革新者
  • 【仿muduo库实现并发服务器】Channel模块