中介者模式(Mediator Pattern)
概念
中介者模式是一种行为型设计模式,它通过引入一个中介对象来封装一系列对象之间的交互,使各对象不需要显式地相互引用,从而降低耦合度。
通俗理解:就像房产中介,买家和卖家不直接联系,都通过中介沟通。中介负责协调双方,处理复杂的交互逻辑。
核心思想
将"做事"和"协调"分离的艺术,让复杂的交互变得简单、可控。
- 同事对象:专注自己的业务能力(做事)
- 中介者:负责编排和协调(指挥)
核心角色
- Mediator(抽象中介者):定义与各同事对象通信的接口
- ConcreteMediator(具体中介者):协调各同事对象实现协作行为,了解并维护各同事对象
- Colleague(抽象同事类):持有中介者引用
- ConcreteColleague(具体同事类):通过中介者与其他同事通信,不直接引用其他同事
问题场景:对象间的网状依赖
没有中介者的情况:
订单服务 ←→ 库存服务
↕ ↕
支付服务 ←→ 通知服务
每个服务都要知道其他服务,形成网状依赖,耦合度高,难以维护。
使用中介者模式:
中介者
↙ ↓ ↓ ↘
订单 库存 支付 通知
所有服务只与中介者通信,形成星型结构,耦合度低。
实际案例:电商下单流程
业务流程:
创建订单 → 扣减库存 → 创建支付单 → 发送通知
传统方式的问题:
class OrderService {
private StockService stockService;
private PaymentService paymentService;
private NotificationService notificationService;
public void createOrder(Order order) {
// 创建订单
saveOrder(order);
// 调用库存服务
stockService.deduct(order);
// 调用支付服务
paymentService.createPayment(order);
// 调用通知服务
notificationService.send(order);
// 如果任何环节失败,回滚逻辑分散在各处,容易出错
}
}
使用中介者模式:
class OrderMediator {
private OrderService orderService;
private StockService stockService;
private PaymentService paymentService;
private NotificationService notificationService;
public void processOrder(Order order) {
try {
// 协调各服务按顺序执行
orderService.create(order);
stockService.deduct(order);
paymentService.createPayment(order);
notificationService.send(order);
} catch (Exception e) {
// 集中处理回滚逻辑
rollback(order);
}
}
private void rollback(Order order) {
// 统一的回滚协调逻辑
notificationService.cancelNotification(order);
paymentService.cancelPayment(order);
stockService.restore(order);
orderService.cancel(order);
}
}
优势
- 降低耦合:各同事对象不需要相互引用
- 集中控制:交互逻辑集中在中介者,易于理解和维护
- 简化对象:同事对象不需要知道复杂的交互逻辑
- 易于扩展:新增同事对象只需修改中介者
缺点
- 中介者可能变得非常复杂,成为"上帝类"
- 中介者本身可能成为性能瓶颈
适用场景
- 对象之间存在复杂的引用关系,导致依赖混乱
- 想通过一个中间类来封装多个类的行为
- 想要复用一个对象,但该对象与其他对象紧密耦合
备忘录模式(Memento Pattern)
概念
备忘录模式是一种行为型设计模式,它允许在不破坏封装性的前提下,捕获并保存一个对象的内部状态,以便在将来某个时刻恢复到该状态。
通俗理解:就像游戏的存档功能,可以随时保存当前进度,打不过BOSS时可以读档重来。
核心思想
给对象拍快照,需要时可以回滚。关键是在保存状态的同时,不破坏对象的封装性。
核心角色
- Originator(发起人):需要保存状态的对象,可以创建备忘录并恢复状态
- Memento(备忘录):存储发起人的内部状态,只有发起人能访问备忘录的内部状态
- Caretaker(管理者):负责保存备忘录,但不能修改或查看备忘录的内容
实际应用场景
1. 文本编辑器的撤销功能
class TextEditor {
private String content;
// 创建备忘录
public Memento save() {
return new Memento(content);
}
// 恢复状态
public void restore(Memento memento) {
this.content = memento.getContent();
}
}
// 使用
TextEditor editor = new TextEditor();
editor.write("Hello");
Memento save1 = editor.save(); // 保存状态
editor.write(" World");
Memento save2 = editor.save();
editor.restore(save1); // 撤销到"Hello"
2. 数据库事务
3. 浏览器的后退功能
4. 游戏存档系统
优缺点
优点:
- 提供了状态恢复机制
- 保持了封装性,不暴露对象内部细节
- 简化了发起人类,状态管理由管理者负责
缺点:
- 消耗资源,每次保存都需要创建备忘录对象
- 如果状态数据很大,会占用大量内存
注意事项
- 备忘录对象应该是不可变的(Immutable)
- 考虑使用原型模式来创建备忘录
- 可以设置备忘录数量上限,避免内存溢出
观察者模式(Observer Pattern)
概念
观察者模式是一种行为型设计模式,它定义了对象之间的一对多依赖关系。当一个对象(被观察者/主题)的状态发生改变时,所有依赖于它的对象(观察者)都会得到通知并自动更新。
通俗理解:就像订阅公众号,你关注了某个公众号(被观察者),当它发布新文章时,所有关注者(观察者)都会收到推送通知。
核心思想
建立一种"订阅-发布"的依赖关系,让对象之间的通信从"主动调用"变成"被动通知"。
关键转变:
- 传统方式:A主动调用B、C、D(A需要知道B、C、D的存在)
- 观察者模式:A发布事件,B、C、D自动收到通知(A不需要知道谁在监听)
核心角色
- Subject(主题/被观察者):维护观察者列表,提供注册、移除、通知观察者的方法
- Observer(观察者):定义更新接口,当收到通知时执行相应操作
- ConcreteSubject(具体主题):存储状态,状态改变时通知所有观察者
- ConcreteObserver(具体观察者):实现更新接口,保持与主题状态的一致
代码对比
没有观察者模式 - 紧耦合:
public class OrderService {
private EmailService emailService;
private SmsService smsService;
private PointsService pointsService;
public void createOrder(Order order) {
// 保存订单
orderRepository.save(order);
// 主动调用各个服务 - 强依赖
emailService.sendEmail(order);
smsService.sendSms(order);
pointsService.addPoints(order);
// 如果要加新功能(如推送通知),必须修改这里
// pushService.push(order); // 违反开闭原则
}
}
使用观察者模式 - 解耦:
public class OrderService {
private List<OrderObserver> observers = new ArrayList<>();
public void addObserver(OrderObserver observer) {
observers.add(observer);
}
public void createOrder(Order order) {
orderRepository.save(order);
// 只负责通知,不关心谁在监听
notifyObservers(order);
}
private void notifyObservers(Order order) {
for (OrderObserver observer : observers) {
observer.update(order);
}
}
}
// 新增功能只需要注册新的观察者,无需修改OrderService
orderService.addObserver(new EmailObserver());
orderService.addObserver(new SmsObserver());
orderService.addObserver(new PointsObserver());
orderService.addObserver(new PushObserver()); // 新增功能
实际应用场景
- 事件监听系统(GUI编程中的按钮点击事件)
- 消息队列(Kafka、RabbitMQ的发布订阅模式)
- Spring的事件机制(ApplicationEvent)
- 数据绑定(Vue、React的响应式数据)
优缺点
优点:
- 降低耦合度,主题和观察者之间是抽象耦合
- 支持广播通信
- 符合开闭原则,增加新观察者无需修改主题
缺点:
- 如果观察者很多,通知会花费较多时间
- 如果观察者和主题之间有循环依赖,可能导致系统崩溃
- 观察者不知道主题如何变化,只知道变化发生了
429



被折叠的 条评论
为什么被折叠?



