中介者设计模式
1. 简单介绍
中介者设计模式(Mediator)是一种行为型设计模式。该模式引入中介对象来封装一系列的对象交互,并使这一系列的对象之间原本需要相互调用的依赖关系,全部转成对中介对象的单独依赖,即将多个对象的依赖关系由网状模型的转变成星状模型,从而使多个对象之间松耦合。
2. 使用场景
- 系统中对象之间存在比较复杂的引用关系,导致他们之间的依赖关系结构混乱而且难以复用该对象,可以引入中介这模式,将多个逻辑关联的对象之间进行解耦
3. 场景举例
DataX
是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括MySQL
、Oracle
、SqlServer
、Postgre
、HDFS
、Hive
、ADS
、HBase
、TableStore(OTS)
、MaxCompute(ODPS)
、DRDS
等各种异构数据源之间高效的数据同步功能。DataX
其实相当于一个中介,从数据源读取数据,写入到目标端,数据源不再需要维护到目标端的同步作业,只需要与DataX
通信即可。DataX
体现了中介者模式的思想。
4. UML类图
5. 具体实现
描述
- 背景:买房者、卖房子通过告知房屋中介,各自的房屋买卖预期心里价位,由中介来判断是否进行交易。如果买卖双方心里预期价位一直,则交易成功,否则交易失败
- Colleague:抽象同事类
- BuyerColleague:卖家,对应设计模式中的具体同事角色
- SellerColleague:卖家,对应设计模式中的具体同事角色
- Mediator:抽象中介者类,对应中介者模式中的Mediator角色
- HousingAgent:房屋中介者,对应中介者模式中的具体中介者
代码实现
Mediator.java
/**
* 抽象中介者类,对应中介者模式中的Mediator角色
*/
public abstract class Mediator {
/**
* 具体同事类注册到中介者
* @param colleague 具体同事
*/
public abstract void register(Colleague colleague);
/**
* 供同事类调用
* 买家(或卖家)注册到中介者中之后,通过调用该方法买告诉中介公司自己的买房要求(卖方要求)
*/
public abstract void agent();
}
HousingAgent.java
/**
* 房屋中介者,对应中介者模式中的具体中介者
*/
public class HousingAgent extends Mediator {
private Map<String, Colleague> colleagueMap = new HashMap<>();
@Override
public void register(Colleague colleague) {
colleagueMap.put(colleague.getName(), colleague);
}
@Override
public void agent() {
Colleague seller = colleagueMap.get("seller");
Colleague buyer = colleagueMap.get("buyer");
if (seller != null && buyer != null) {
int sellerExpectedHousePrices = seller.getExpectedHousePrices();
int buyerExpectedHousePrices = buyer.getExpectedHousePrices();
if (buyerExpectedHousePrices >= sellerExpectedHousePrices) {
System.out.println("买卖双方房屋期望价格一直,完成交易");
} else {
System.out.println("卖家出售房屋价格高于买家预期,停止交易");
}
} else if (seller != null) {
System.out.println("等待买家出价");
} else {
System.out.println("等待卖家出价");
}
}
}
Colleague.java
/**
* 抽象同事类,对应中介者模式中的Colleague角色
*/
public abstract class Colleague {
private Mediator mediator;
/**
* 买家、卖家心中预期房子售价价位
*/
private int expectedHousePrices;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
/**
* 标识具体同事类的名称
*/
public abstract String getName();
public void sendAppeal() {
mediator.agent();
}
public int getExpectedHousePrices() {
return expectedHousePrices;
}
public void setExpectedHousePrices(int expectedHousePrices) {
this.expectedHousePrices = expectedHousePrices;
}
}
BuyerColleague.java
/**
* 买家,对应设计模式中的具体同事角色
*/
public class BuyerColleague extends Colleague {
public BuyerColleague(Mediator mediator) {
super(mediator);
}
@Override
public String getName() {
return "buyer";
}
}
SellerColleague.java
/**
* 卖家,对应设计模式中的具体同事角色
*/
public class SellerColleague extends Colleague {
public SellerColleague(Mediator mediator) {
super(mediator);
}
@Override
public String getName() {
return "seller";
}
}
7. 源码展示
JDK
中的Timer
类在任务调度设计中采用了中介者设计模式的思想。待处理的任务(TimeTask)通过添加(注册)到Timer类中,何时调用由Timer进行管理。其中TimerTask对应中介者模式中的Colleague角色,Timer对应中介者模式中的ConcreteMediator角色。主要核心代码如下:
Timer.java
/**
* 对应中介者模式中的ConcreteMideator角色
*/
public class Timer {
/**
* 存放任务的(具体同事对象)队列
*/
private final TaskQueue queue = new TaskQueue();
/**
* 任务交给Timer进行管理
*/
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 0);
}
/**
* 控制着任务的入队,任务之间入队执行存在的线程安全问题全部交由中介者Timer处理
*/
private void sched(TimerTask task, long time, long period) {
if (time < 0)
throw new IllegalArgumentException("Illegal execution time.");
// Constrain value of period sufficiently to prevent numeric
// overflow while still being effectively infinitely large.
if (Math.abs(period) > (Long.MAX_VALUE >> 1))
period >>= 1;
synchronized(queue) {
if (!thread.newTasksMayBeScheduled)
throw new IllegalStateException("Timer already cancelled.");
synchronized(task.lock) {
if (task.state != TimerTask.VIRGIN)
throw new IllegalStateException(
"Task already scheduled or cancelled");
task.nextExecutionTime = time;
task.period = period;
task.state = TimerTask.SCHEDULED;
}
queue.add(task);
if (queue.getMin() == task)
queue.notify();
}
}
/**
* 任务的具体执行
*/
public void run() {
try {
// 控制者任务的具体执行过程
mainLoop();
} finally {
// Someone killed this Thread, behave as if Timer cancelled
synchronized(queue) {
newTasksMayBeScheduled = false;
queue.clear(); // Eliminate obsolete references
}
}
}
}
TimeTask.java
public abstract class TimerTask implements Runnable {
protected TimerTask() {
}
/**
* 子类重写该方法完成具体的任务逻辑
* 任务交由Timer类进行管理、调用
*/
public void abstract run();
}