定义
用一个中介对象来封装一系列对象之间的交互。中介者使各个对象不需要显式的相互引用,从而使其耦合松散,并且可以独立的改变它们之间的交互。
结构图
Colleague叫做抽象同事类(接口),ConcreteColleague是具体同事类,每个具体同事类只知道自己的行为,而不了解其他同事类的情况,但它们都认识中介者对象;Mediator是抽象中介者,定义了同事对象到中介者对象之间的接口,ConcreteMediator是具体中介者对象,实现抽象类的方法,它需要知道所有具体同事类,并从具体同事接受消息,向具体同事对象发出命令。
核心
- 如果一个系统中对象之间的关系呈现网状结构,对象之间存在大量多对多关系,将导致关系及其复杂,这些对象称为“同事对象”。
- 我们可以引入一个中介者对象,使各个同事对象只跟中介者对象打交道,将复杂的网状结构化解为星型结构。
解耦多个同事对象之间的交互关系,每个对象都持有中介者对象的引用,只跟中介者对象打交道。通过中介者对象统一管理这些交互关系。
场景
- 假设公司没有总经理,但又三个部门:财务部、市场部、研发部。财务部需要发工资,让大家核对工资需要跟市场部和研发部都联系通气;市场部接个新项目,需要研发部提供技术,财务部提供资金;市场部跟各个部门打交道,关系非常乱。
- 实际上,公司都是有总经理的,各个部门有需求都报告总经理,然后总经理再通知相关部门。
- 这就是一个中介者模式:总经理起到一个中介、协调的作用。
代码实现
- 首先定义同事类抽象接口Department,有两个方法selfAction()和outAction(),分别为干自己的事和汇报工作。
/**
* User:tumbler
* Desc:中介者模式--同事类接口
*/
public interface Department {
/**
* 做自己部门的工作
*/
void selfAction();
/**
* 向中介者(总经理)发送申请
*/
void outAction();
}
- 定义中介者抽象接口Mediator,有两个方法register() 注册部门,command()向部门发送指令。
/**
* User:tumbler
* Desc:中介者模式--中介者接口
*/
public interface Mediator {
/**
* 注册部门,与中介者产生关系
* @param dName 部门名称
* @param department 具体部门
*/
void register(String dName, Department department);
/**
* 中介者向任意部门发送命令
* @param dName 部门名称
*/
void command(String dName);
}
- 定义具体同事类,研发部,市场部,财务部。
/**
* User:tumbler
* Desc:中介者模式--具体同事类--研发部
* 持有中介者(总经理)对象,实现同事类接口Department
*/
public class Development implements Department {
private Mediator mediator;
public Development(Mediator mediator) {
this.mediator = mediator;
//向中介者注册,互相持有
mediator.register("development", this);
}
@Override
public void selfAction() {
System.out.println("钻研技术,开发项目!");
}
@Override
public void outAction() {
System.out.println("汇报工作!研发部没钱了,需资金支持");
//通过中介向财务部发消息
mediator.command("finacial");
}
}
/**
* User:tumbler
* Desc:中介者模式--具体同事类--市场部
* 持有中介者(总经理)对象,实现同事类接口Department
*/
public class Market implements Department {
private Mediator mediator;
public Market(Mediator mediator) {
this.mediator = mediator;
//向中介者注册,互相持有
mediator.register("market", this);
}
@Override
public void selfAction() {
System.out.println("专心接项目!");
}
@Override
public void outAction() {
System.out.println("汇报工作!承接项目,需要资金支持。");
//通过中介向财务部发消息
mediator.command("finacial");
}
}
/**
* User:tumbler
* Desc:中介者模式--具体同事类--财务部
* 持有中介者(总经理)对象,实现同事类接口Department
*/
public class Finacial implements Department {
private Mediator mediator;
public Finacial(Mediator mediator) {
this.mediator = mediator;
//向中介者注册,互相持有
mediator.register("finacial", this);
}
@Override
public void selfAction() {
System.out.println("数钱数到手抽筋!");
}
@Override
public void outAction() {
System.out.println("汇报工作!钱太多了,怎么花?");
}
}
- 定义具体中介者类,总经理President, 实现抽象中介者接口
/**
* User:tumbler
* Desc:中介者模式--具体中介者--总经理
*/
public class President implements Mediator {
//存放具体同事类
private Map<String, Department> map = new HashMap<>();
@Override
public void register(String dName, Department department) {
map.put(dName, department);
}
@Override
public void command(String dName) {
map.get(dName).selfAction();
}
}
- 测试Client
/**
* User:tumbler
* Desc:中介者模式--测试类
*/
public class Client {
public static void main(String[] args) {
//中介者
Mediator mediator = new President();
//具体同事类,都持有中介者
Department development = new Development(mediator);
Department market = new Market(mediator);
Department finacial = new Finacial(mediator);
market.selfAction();
market.outAction();
}
}
这里市场部向总经理汇报工作,然后通过中介者总经理想财务部申请资金,财务部收到后数钱,运行结果如下:
专心接项目!
汇报工作!承接项目,需要资金支持。
数钱数到手抽筋!
- UML图
开发常见应用
- MVC模式中的C,控制器就是一个中介者,M和V都和它打交道。
- 窗口游戏程序,窗口软件开发中窗口对象也是一个中介者对象。
- 图形界面开发GUI中,多个组件之间交互,可以引入中介者对象来解决,可以是整体的窗口对象或者是DOM对象。
- java.lang.reflect.Method#invoke()
总结
- 中介者模式很容易在系统中应用,也很容易误用。当系统出现了“多对多”复杂的对象群时,不要急于使用中介者模式,而要先思考系统是否在设计上合理。
- Mediator的出现减少了各个Colleague的耦合,使得可以独立的改变和复用Colleague和Mediator类。
- 中介者模式把对象如何写作进行了抽象,将中介者作为一个独立的概念并封装成一个对象,这样关注的对象就从对象各自本身的行为转换到他们之间的交互上来,也就是站在一个更宏观的角度看待系统。
- 由于ConcreteMediator控制了集中化,于是就把 交互复杂性变为中介者的复杂性,这就使得中介者就会变得比任何一个ConcreteColleague都复杂。