《设计模式》中介者模式
定义:
- 中介者模式又称为调停者模式,用一个中介对象封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其可以松散耦合,独立地改变它们之间的交互。
- 属于行为型设计模式。
中介者模式的角色组成:
- Mediator(抽象中介者):定义统一的接口,用于各个同事角色之间的通信。
- ConcreteMediator(具体中介者):维持对各个同事对象的引用,从具体的同事对象接收消息,向具体同事对象发出命令,通过协调各个同事对象来实现协作行为。
- Colleague(抽象同事):定义各个同事类公有的方法,并声明了一些抽象方法来供子类实现,同时维持了一个对抽象中介者类的引用,其子类可以通过该引用来与中介者通信。
- ConcreteColleague(具体同事类):实现了在抽象同事类中声明的抽象方法,每一个同事对象在需要和其他同事对象通信时先与中介者通信,通过中介者来间接完成与其他同事类的通信。
中介者模式的 UML 类图:
🎈情景案例:生活中的租房情景就是中介者模式的体现,房东和租客以及租房中介分别充当了同事和中介者角色:房东将房屋托管给租房中介,而租客从租房中介那边获取房源信息,租房中介充当房东和租客之间的中介者。
抽象中介者 Mediator
:
public interface Mediator {
void contact(String message, Person person);
}
抽象同事 Person
:
public abstract class Person {
protected String name;
protected Mediator mediator;
public Person(String name, Mediator mediator) {
this.name = name;
this.mediator = mediator;
}
}
具体同事房东 LandLord
:
public class LandLord extends Person {
public LandLord(String name, Mediator mediator) {
super(name, mediator);
}
public void contact(String message) {
mediator.contact(message, this);
}
public void getMessage(String message) {
System.out.println("房东" + name + "获取的信息是:" + message);
}
}
具体同事租客 Tenant
:
public class Tenant extends Person {
public Tenant(String name, Mediator mediator) {
super(name, mediator);
}
public void contact(String message) {
mediator.contact(message, this);
}
public void getMessage(String message) {
System.out.println("租客" + name + "获取的信息是:" + message);
}
}
具体中介者租房机构 MediatorOrgan
:
public class MediatorOrgan implements Mediator {
private LandLord landLord;
private Tenant tenant;
public LandLord getLandLord() {
return landLord;
}
public void setLandLord(LandLord landLord) {
this.landLord = landLord;
}
public Tenant getTenant() {
return tenant;
}
public void setTenant(Tenant tenant) {
this.tenant = tenant;
}
@Override
public void contact(String message, Person person) {
if (person == landLord) {
tenant.getMessage(message);
} else {
landLord.getMessage(message);
}
}
}
调用的客户端 Client
:
public class Client {
public static void main(String[] args) {
MediatorOrgan mediatorOrgan = new MediatorOrgan();
LandLord landLord = new LandLord("包租婆", mediatorOrgan);
Tenant tenant = new Tenant("小伙汁", mediatorOrgan);
mediatorOrgan.setLandLord(landLord);
mediatorOrgan.setTenant(tenant);
tenant.contact("我需要租包租婆的房子");
landLord.contact("小伙汁,我的房子还在可以租给你");
}
}
中介者模式的优点:
- 将同事对象解耦:中介者的出现减少了各个同事对象的耦合,使得可以独立地改变和复用各个同事和中介者。
- 简化对象之间的交互:中介者模式使用中介者和同事的一对多交互代替了原来同事之间的多对多交互。一对多关系更容易理解、维护和扩展,将原本难以理解的网状结构转换成相对简单的星形结构。
中介者模式的缺点:
- 在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
中介者模式的适用场景:
- 系统中对象之间存在复杂的引用关系,结构混乱难以理解。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
🎈中介者模式在JDK源码
java.util.Timer
中的应用
Timer
类用于创建定时器任务。它充当了一个中介者的角色,负责协调计时器任务的创建和执行。通过 Timer
类,我们可以创建定时任务,设置任务的执行时间和间隔,并且可以取消已经创建的任务。
定时器Timer
类部分源码如下:
public class Timer {
// ...
public void schedule(TimerTask task, long delay) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
sched(task, System.currentTimeMillis()+delay, 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();
}
}
// ...
}
无论什么样的任务都被加入一个队列中按顺序执行,该队列中的所有对象都称为“同事”,同事之间的通信都是通过Timer
来协调完成的,Timer
承担了中介者的角色。