1. 中介者模式(Command Pattern)
1.1 介绍
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
-
主要解决 :对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
-
如何解决 :将上述网状结构分离为星星结构
-
关键代码 :对象 Colleague 之间的通信封装到一个类中单独处理
1.2 优缺点
优点
- 降低了类的复杂度,将一对多转化成了一对一
- 各个类之间的解耦
- 使用了中介者模式之后,各个类都各司其职,符合了迪米特法则。
缺点
- 当我们的同事角色非常多的时候,中介者对象需要维护非常多的同事角色对象,会使得中介者变得非常庞大,导致难以维护。
1.3 使用场景
- 系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
1.4 注意事项
不应当在职责混乱的时候使用。
2. 案例实现
我们发现得到的宝物竟然是三本书,这可把我们气个半死,但当我定睛一看,这三本书竟然不是普通的教科书,而是很牛很牛的书,所以我们决定卖个好价钱,但是怕暴露自身而引来灾祸,我们决定找个中介来帮我们卖书。
最后3本书卖了3个亿人民币,我和我朋友一人1亿,最后过上了无忧无虑的幸福生活。(剧终)
// 拍卖行
public class Auction {
public static void sellBook(Me me, String book){
System.out.println("卖"+book+"啦");
}
}
public class Me {
public void sell(String book){
Auction.sellBook(this, book);
}
}
/**
* 中介者模式
*
*@Author cly
*@Date 2021/09/01 0:35
*@Version 1.0
*/
public class Mediator {
public static void main(String[] args) {
Me me = new Me();
me.sell("语文书");
me.sell("数学书");
me.sell("英语书");
}
}
3. 源码实现
3.1 Timer类
我们打开JDK源码中的Timer类。我们任意查看其中的几个schedule方法:可以看到,所有的task都放入了Timer类中维护的task队列中。所以Timer就是充当了一个中介者的角色,而task队列内的任务就是具体同事对象。
public void schedule(TimerTask task, Date time) {
sched(task, time.getTime(), 0);
}
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();
}
}