一, 什么是中介者模式
中介这个词并不陌生, 就是房屋中介的那个 "中介", 就是中间人的意思. 比如 MVC 模式, C(Controller 控制器) 是 M(Model 模型) 和 V(View 视图) 的中介者, 在前后端交互时起到了中间人的作用.
中介者模式 (Mediator), 用一个中介对象来封装一系列的对象交互. 中介者使各个对象不需要显式地相互引用, 从而使其耦合松散, 而且可以独立地改变它们之间的交互. UML 结构图如下:
其中, Mediator 是抽象中介者, 定义了同事对象到中介者对象的接口; Colleague 是抽象同事类; ConcreteMediator 是具体中介者对象, 实现抽象类的方法, 它需要知道所有具体同事类, 并从具体同事接收消息, 向具体同事对象发出命令; ConcreteColleague 是具体同事类, 每个具体同事只知道自己的行为, 而不了解其它同事类的情况, 但它们却都认识中介者对象.
1. 抽象中介者
抽象中介者角色定义统一的接口, 用于各同事角色之间的通信.
- public abstract class Mediator {
- // 抽象的发送消息方法
- public abstract void send(String message, Colleague colleague);
- }
2. 抽象同事类
每一个同事角色都知道中介者角色, 而且与其它的同事角色通信的时候, 一定要通过中介者角色协作. 每个同事类的行为分两种: 一种是同事本身行为, 比如改变对象本身的状态, 处理自己的行为等, 这种行为叫做自发行为, 与其它同事类或者中介者没有任何依赖; 第二种是必须依赖中介者才能完成的行为, 叫做依赖方法.
- public abstract class Colleague {
- protected Mediator mediator;
- public Colleague(Mediator mediator) {
- this.mediator = mediator;
- }
- }
3. 具体中介者类
具体中介者角色通过协调各同事角色实现协作行为, 因此它必须依赖于各个同事角色.
- public class ConcreteMediator extends Mediator {
- private ConcreteColleague1 colleague1;
- private ConcreteColleague2 colleague2;
- public void setColleague1(ConcreteColleague1 colleague1) {
- this.colleague1 = colleague1;
- }
- public void setColleague2(ConcreteColleague2 colleague2) {
- this.colleague2 = colleague2;
- }
- @Override
- public void send(String message, Colleague colleague) {
- if(colleague == colleague1) {
- colleague2.notify(message);
- } else {
- colleague1.notify(message);
- }
- }
- }
4. 具体同事类
这里以 ConcreteColleague1 为例, ConcreteColleague2 不再赘述.
- public class ConcreteColleague1 extends Colleague {
- public ConcreteColleague1(Mediator mediator) {
- super(mediator);
- }
- public void send(String message) {
- mediator.send(message, this);
- }
- public void notify(String message) {
- System.out.println("同事 1 得到消息:" + message);
- }
- }
5. Client 客户端
首先创建一个具体中介者对象, 然后实例化两个具体同事类并与该中介者进行绑定, colleague1 与 colleague2 通过中介者发送信息.
- public class Client {
- public static void main(String[] args) {
- ConcreteMediator mediator = new ConcreteMediator();
- ConcreteColleague1 colleague1 = new ConcreteColleague1(mediator);
- ConcreteColleague2 colleague2 = new ConcreteColleague2(mediator);
- mediator.setColleague1(colleague1);
- mediator.setColleague2(colleague2);
- colleague1.send("Nice to meet u.");
- colleague2.send("Nice to meet u too.");
- }
- }
运行结果如下:
二, 中介者模式的应用
1. 何时使用
多个类相互耦合, 形成网状结构时
2. 方法
将网状结构分离为星型结构
3. 优点
减少类间依赖, 降低了耦合
符合迪米特原则
4. 缺点
中介者会膨胀的很大, 而且逻辑复杂
5. 使用场景
系统中对象之间存在比较复杂的引用关系
想通过一个中间类来封装多个类的行为, 而又不想生成太多的子类
6. 应用实例
联合国 / WTO 作为中介者协调各个国家
房屋中介 / 机场调度系统
MVC 框架, 其中 C(Contorller 控制器) 是 M(Model 模型) 和 V(View 视图) 的中介者
7. 注意事项
不应当在职责混乱时使用
三, 中介者模式的实现
上面我们有提到, 联合国作为一个由各国代表组成, 用来维护国际和平与安全, 解决国际间经济, 社会, 文化和人道主义性质的问题的角色, 它就是一个调停者, 中介者的角色, 国与国直接完全完全可以通过 "联合国" 这个中介者来发生关系, 而不用直接通信.
下面就以联合国安理会作为中介者, 了解一下中介者模式. UML 图如下:
1. 联合国机构
抽象中介者.
- public abstract class UnitedNations {
- public abstract void declare(String message, Country country);
- }
2. 国家类
抽象国家类, 需声明中介者角色.
- public class Country {
- protected UnitedNations unitedNations;
- public Country(UnitedNations unitedNations) {
- this.unitedNations = unitedNations;
- }
- }
3. 具体国家类
具体国家类, 继承了抽象国家类. 这里以 USA 类为例, Iraq 类不再赘述.
- public class USA extends Country {
- public USA(UnitedNations unitedNations) {
- super(unitedNations);
- }
- public void declare(String message) {
- unitedNations.declare(message, this);
- }
- public void getMessage(String message) {
- System.out.println("美国获得对方信息:" + message);
- }
- }
4. 联合国安理会
具体中介者角色, 继承抽象中介者, 重写其 declare() 方法, 对不同国家发送不同信息.
- public class UnitedNationsSecurityCouncil extends UnitedNations {
- private USA usa;
- private Iraq iraq;
- public void setUsa(USA usa) {
- this.usa = usa;
- }
- public void setIraq(Iraq iraq) {
- this.iraq = iraq;
- }
- @Override
- public void declare(String message, Country country) {
- if(country == usa) {
- iraq.getMessage(message);
- } else {
- usa.getMessage(message);
- }
- }
- }
5. Client 客户端
实例化一个联合国安理会对象, 两国通过联合国安理会进行对话.
- public class Client {
- public static void main(String[] args) {
- UnitedNationsSecurityCouncil UNSC = new UnitedNationsSecurityCouncil();
- USA usa = new USA(UNSC);
- Iraq iraq = new Iraq(UNSC);
- UNSC.setUsa(usa);
- UNSC.setIraq(iraq);
- usa.declare("不准研制核武器");
- iraq.declare("我们没有核武器");
- }
- }
运行结果如下:
源码地址: https://gitee.com/adamjiangwh/GoF
来源: https://www.cnblogs.com/adamjwh/p/10959987.html