设计模式——中介者设计模式(行为型)
摘要
文章详细介绍了中介者设计模式,这是一种行为型设计模式,通过中介者对象封装多个对象间的交互,降低系统耦合度。文中阐述了其核心角色、优缺点、适用场景,并通过类图、时序图、实现方式、实战示例等多方面进行讲解,还探讨了与其他设计模式的组合使用,帮助读者全面理解该模式。
1. 中介者设计模式定义
中介者设计模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介对象来封装多个对象之间的交互,从而使对象之间不再互相引用,降低系统的耦合度,让对象之间的通信通过中介者统一协调。
飞机起降管控系统:多架飞机(同事对象)之间不能自己协调起降,必须通过“塔台”(中介者)统一调度,这样飞机之间不需要知道彼此,只需与塔台通信。
1.1. 📌 核心角色
角色 | 说明 |
Mediator | 抽象中介者,定义对象之间通信的接口 |
ConcreteMediator | 具体中介者,实现协调各组件之间的交互逻辑 |
Colleague | 同事类,每个与其他对象通信的对象,只与中介者通信 |
1.2. ✅ 优点
- 降低对象之间的耦合,避免“网状结构”,变为“星型结构”
- 交互集中管理,逻辑清晰、易维护
- 更易于扩展和修改通信规则
1.3. ❌ 缺点
- 中介者可能变得非常复杂,成为“上帝类”
- 不适合同事对象数量很少、交互简单的情况
1.4. ✅ 适用场景
- 多个对象之间存在复杂交互,导致系统结构混乱
- 希望将对象间的通信行为提取到一个独立类中进行管理
- 界面组件交互(如按钮、输入框等)、聊天系统、协作系统
2. 中介者设计模式结构
- 组件 (Component) 是各种包含业务逻辑的类。 每个组件都有一个指向中介者的引用, 该引用被声明为中介者接口类型。 组件不知道中介者实际所属的类, 因此你可通过将其连接到不同的中介者以使其能在其他程序中复用。
- 中介者 (Mediator) 接口声明了与组件交流的方法, 但通常仅包括一个通知方法。 组件可将任意上下文 (包括自己的对象) 作为该方法的参数, 只有这样接收组件和发送者类之间才不会耦合。
- 具体中介者 (Concrete Mediator) 封装了多种组件间的关系。 具体中介者通常会保存所有组件的引用并对其进行管理, 甚至有时会对其生命周期进行管理。
2.1. 中介者模式类图
2.2. 中介者模式时序图
3. 中介者设计模式实现方式
中介者设计模式是一种行为型设计模式,通过引入中介对象封装多个对象之间的交互,从而使对象之间不再互相引用,达到松耦合的目的。
3.1. 🧱 核心实现结构
3.1.1. 抽象中介者接口(Mediator
)
定义统一的通信接口,用于同事对象之间的协调。
public interface Mediator {void notify(String event, Colleague sender);
}
3.1.2. 抽象同事类(Colleague
)
每个同事类都持有中介者的引用,只与中介者通信。
public abstract class Colleague {protected Mediator mediator;public Colleague(Mediator mediator) {this.mediator = mediator;}
}
3.1.3. 具体同事类(ConcreteColleague
)
具体的业务类,通过调用中介者来进行通信。
public class ConcreteColleagueA extends Colleague {public ConcreteColleagueA(Mediator mediator) {super(mediator);}public void doSomething() {System.out.println("ColleagueA 执行操作,通知中介者");mediator.notify("A完成", this);}public void receive(String msg) {System.out.println("ColleagueA 收到消息:" + msg);}
}
public class ConcreteColleagueB extends Colleague {public ConcreteColleagueB(Mediator mediator) {super(mediator);}public void doSomething() {System.out.println("ColleagueB 执行操作,通知中介者");mediator.notify("B完成", this);}public void receive(String msg) {System.out.println("ColleagueB 收到消息:" + msg);}
}
3.1.4. 具体中介者类(ConcreteMediator
)
负责协调同事类之间的通信逻辑。
public class ConcreteMediator implements Mediator {private ConcreteColleagueA colleagueA;private ConcreteColleagueB colleagueB;public void setColleagueA(ConcreteColleagueA a) {this.colleagueA = a;}public void setColleagueB(ConcreteColleagueB b) {this.colleagueB = b;}@Overridepublic void notify(String event, Colleague sender) {if (sender == colleagueA) {colleagueB.receive("来自A的通知:" + event);} else if (sender == colleagueB) {colleagueA.receive("来自B的通知:" + event);}}
}
3.2. 🛠 测试用例
public class Main {public static void main(String[] args) {ConcreteMediator mediator = new ConcreteMediator();ConcreteColleagueA a = new ConcreteColleagueA(mediator);ConcreteColleagueB b = new ConcreteColleagueB(mediator);mediator.setColleagueA(a);mediator.setColleagueB(b);a.doSomething();b.doSomething();}
}
3.3. ✅ 输出示例
ColleagueA 执行操作,通知中介者
ColleagueB 收到消息:来自A的通知:A完成
ColleagueB 执行操作,通知中介者
ColleagueA 收到消息:来自B的通知:B完成
3.4. 🧩 中介者示例总结
角色 | 职责 |
Mediator | 定义中介者接口,协调同事之间的通信 |
ConcreteMediator | 持有所有同事的引用,封装对象间交互逻辑 |
Colleague | 持有中介者引用,通过中介者与其他对象交互,不直接引用其他对象 |
应用价值 | 解耦多个对象间复杂的网状关系,转化为中心化的星型结构,便于扩展和维护 |
4. 中介者设计模式适合场景
4.1. ✅ 中介者设计模式适合场景
场景描述 | 说明 |
多个对象间复杂交互 | 对象之间交互关系复杂且频繁,使用中介者简化对象间直接通信 |
需要解耦对象之间的依赖 | 通过中介者集中管理,减少对象之间的耦合,符合单一职责原则 |
系统中的对象之间通信逻辑经常变化 | 中介者封装交互逻辑,修改交互规则只需改中介者,不用改对象 |
多个模块协作实现复杂业务流程 | 中介者协调不同模块协作,避免各模块直接耦合 |
需要统一管理和监控对象间通信 | 中介者作为统一中心,便于增加日志、监控、事务控制等功能 |
4.2. ❌ 中介者设计模式不适合场景
对象间通信关系简单,耦合不明显 | 使用中介者会增加不必要的复杂度,直接通信更清晰简单 |
对象数量非常少 | 中介者的抽象和管理成本超过了实际收益 |
性能要求极高,不允许通信中间层增加延迟 | 中介者引入了额外的转发和协调,可能导致一定的性能损耗 |
系统逻辑对对象的独立性和自治性要求较高 | 中介者集中控制会限制对象自治,增加耦合 |
需要灵活、动态调整对象间通信方式 | 中介者模式较为静态,频繁调整通信机制可能导致中介者复杂难维护 |
5. 中介者设计模式实战示例
下面给你一个基于Spring框架,使用注解注入,非构造函数注入的中介者设计模式实战示例,场景是简化版金融风控系统中多个风控模块(比如信用评分模块、额度计算模块)之间的协作。
5.1. 设计思路
- 中介者接口:定义协调各风控模块交互的方法
- 具体中介者类:实现接口,注入各风控模块,协调调用
- 风控模块接口:所有风控模块统一接口
- 具体风控模块实现类:业务模块实现
5.2. 中介者接口
public interface RiskMediator {void execute(String action);
}
5.3. 风控模块接口
public interface RiskModule {void check();
}
5.4. 具体风控模块实现
import org.springframework.stereotype.Component;@Component
public class CreditScoreModule implements RiskModule {@Overridepublic void check() {System.out.println("信用评分模块风控校验...");}
}@Component
public class CreditLimitModule implements RiskModule {@Overridepublic void check() {System.out.println("额度计算模块风控校验...");}
}
5.5. 具体中介者实现(协调模块)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Component
public class RiskMediatorImpl implements RiskMediator {// 非构造函数注入@Autowiredprivate CreditScoreModule creditScoreModule;@Autowiredprivate CreditLimitModule creditLimitModule;@Overridepublic void execute(String action) {switch (action) {case "creditCheck":creditScoreModule.check();break;case "limitCheck":creditLimitModule.check();break;case "allCheck":creditScoreModule.check();creditLimitModule.check();break;default:System.out.println("未知操作");}}
}
5.6. 业务调用示例(Service)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class RiskService {@Autowiredprivate RiskMediator riskMediator;public void performRiskCheck() {System.out.println("开始风控校验...");riskMediator.execute("allCheck");System.out.println("风控校验完成");}
}
5.7. Spring Boot 主程序测试
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class RiskControlApplication implements CommandLineRunner {@Autowiredprivate RiskService riskService;public static void main(String[] args) {SpringApplication.run(RiskControlApplication.class, args);}@Overridepublic void run(String... args) throws Exception {riskService.performRiskCheck();}
}
5.8. 运行结果
复制编辑
开始风控校验...
信用评分模块风控校验...
额度计算模块风控校验...
风控校验完成
说明
- 中介者对象负责协调多个风控模块,调用对应方法完成协作。
- 如果以后需要新增风控模块,只需在中介者类中添加对应依赖并扩展
execute
方法即可。 - 解耦风控模块之间的直接调用,实现灵活协作。
6. 中介者设计模式思考
6.1. 中介者设计模式常和以下设计模式组合使用,提升系统解耦性、灵活性和可维护性?
设计模式 | 作用 | 组合理由 |
观察者模式 | 事件通知,模块状态变更监听 | 松耦合,异步通知 |
策略模式 | 不同处理策略动态切换 | 灵活行为管理 |
命令模式 | 请求封装,支持撤销、排队 | 请求管理解耦 |
责任链模式 | 按顺序处理请求 | 流程控制与模块责任划分 |
工厂模式 | 创建模块实例 | 解耦模块实例化 |
状态模式 | 根据状态改变行为 | 简化状态管理,增强灵活性 |
6.1.1. 观察者模式(Observer Pattern)
- 场景:中介者作为事件中心,监听模块状态变化并通知相关模块。
- 组合效果:模块状态变化由中介者发起事件通知,避免模块间直接依赖,实现松耦合。
6.1.2. 策略模式(Strategy Pattern)
- 场景:中介者根据不同场景或条件,动态选择不同的处理策略。
- 组合效果:中介者协调不同策略,提升行为灵活性和可扩展性。
6.1.3. 命令模式(Command Pattern)
- 场景:将请求封装成命令对象,中介者负责调用命令,支持请求排队、撤销等操作。
- 组合效果:使请求调用和执行解耦,中介者集中管理命令执行。
6.1.4. 责任链模式(Chain of Responsibility Pattern)
- 场景:多个模块按顺序处理请求,中介者组织责任链,协调链上的处理步骤。
- 组合效果:流程化请求处理,增强模块间协作的灵活控制。
6.1.5. 工厂模式(Factory Pattern)
- 场景:中介者创建或获取模块实例,通过工厂解耦模块创建细节。
- 组合效果:提高模块实例管理灵活性,便于模块替换和扩展。
6.1.6. 状态模式(State Pattern)
- 场景:中介者根据系统或模块状态变化,动态调整模块行为。
- 组合效果:将状态和行为分离,简化中介者的决策逻辑。
6.2. 中介者和观察者模式实战示例
6.2.1. 适用场景对比
模式 | 适用场景 | 特点 |
中介者模式 | 多个组件之间复杂协作、行为依赖,强交互逻辑需要统一协调 | 强中心化,便于流程控制、逻辑清晰,但中介者本身易变复杂 |
观察者模式 | 一个对象状态变化需通知多个对象,多个模块监听某事件或行为 | 弱耦合、支持异步,适合事件驱动架构,但流程控制不集中,追踪困难 |
6.2.2. ✅ 场景 1:金融风控审批系统(使用中介者模式)
业务背景: 用户提交贷款申请,需依次经过以下模块:
- 黑名单检查
- 身份实名认证
- 反欺诈评分
- 授信额度计算
这些模块相互有顺序依赖,并存在交互控制。
✅ 实现方式(中介者模式):
@Component
public class RiskMediator {@Autowired private BlacklistChecker blacklistChecker;@Autowired private IdentityVerifier identityVerifier;@Autowired private AntiFraudEngine antiFraudEngine;@Autowired private CreditScoreCalculator creditScoreCalculator;public RiskResult process(UserApplyDTO apply) {if (!blacklistChecker.check(apply)) return RiskResult.reject("黑名单");if (!identityVerifier.verify(apply)) return RiskResult.reject("身份校验失败");FraudResult fraud = antiFraudEngine.analyze(apply);if (fraud.isHighRisk()) return RiskResult.reject("欺诈嫌疑");return creditScoreCalculator.calculate(apply);}
}
所有风控组件之间不直接通信,由 RiskMediator
协调。
6.2.3. ✅ 场景 2:用户注册发送通知(使用观察者模式)
业务背景: 用户注册成功后,需要:
- 发送欢迎短信
- 推送用户画像同步任务
- 发放注册优惠券
这三个操作彼此独立,不影响主流程。
✅ 实现方式(观察者模式 + Spring Event):
定义事件对象:
public class UserRegisterEvent extends ApplicationEvent {private final Long userId;public UserRegisterEvent(Object source, Long userId) {super(source);this.userId = userId;}public Long getUserId() { return userId; }
}
发布事件:
@Component
public class UserService {@Autowired private ApplicationEventPublisher publisher;public void register(UserDTO dto) {// 注册逻辑...publisher.publishEvent(new UserRegisterEvent(this, dto.getId()));}
}
监听器(观察者):
@Component
public class WelcomeSmsListener {@EventListenerpublic void onRegister(UserRegisterEvent event) {// 发送短信}
}@Component
public class ProfileSyncListener {@EventListenerpublic void onRegister(UserRegisterEvent event) {// 同步画像}
}
Spring 自动管理监听器注册,模块间完全解耦,扩展方便。
6.3. ✅ 中介者和观察者模式总结
目标 | 推荐模式 | 理由 |
统一控制业务流程 | 中介者模式 | 控制逻辑集中,适合复杂流程协调 |
模块间异步通知 | 观察者模式 | 低耦合、事件驱动、支持多个订阅方 |
需要响应式扩展通知 | 观察者模式 | 任意监听器可接入或移除,灵活扩展 |
模块依赖顺序较强 | 中介者模式 | 控制好执行顺序,模块逻辑依赖清晰 |