中介者模式(Mediator Pattern)是一种行为模式(Behavior Design Patters)。中介者模式能够简化多个对象之间的相互交互,并且将对象内部逻辑与相互交互的逻辑分离开。因此,在中介者模式下,能够独立的改变对象之间交互的方式,而不影响对象内部的逻辑。
从下面的示意图中我们可以看到,假设一个系统中有四个对象Object 1, Object 2, Object 3和Object4。它们之间相互调用。更复杂的是,Object 1可能调用了Object 2的一个方法。在该方法返回之前,Object 2可能需要调用Object 3的方法。在Object 3的方法中,可能还需要调用Object 4的方法。这种逐层调用的场景会使得代码逻辑变得更为复杂,难以维护。
图一 中介者模式解决方案。
因此,一个更合理的设计是使用中介者模式来帮助对象之间的调用(交互)。中介者是系统中的一个新的对象,它负责处理和传递对象之间的调用。因此,对于对象而言,它只可能被中介者对象调用。当该对象需要调用其他对象时,它只需要“通知”中介者对象即可。这样的设计极大的简化了对象内部逻辑,也将复杂的调用关系分离并实现在中介者对象中。
在中介者模式中,有四个参与方。
图二 中介者模式结构。
我们使用一个简单的用例来展示中介者模式的用法。这个用例实现了一个简单的、同事之间更新状态的功能。这个用例定义了一个接口ColleagueItf。该接口声明了五个成员方法。其中,getName()返回该同事的姓名。getStatus()/setStatus()分别查询和更新自身的状态。syncStatus()/syncStatusToColleague()方法则向其他同事更新自身的状态。MediatorItf接口定义了中介者的职责。成员方法register()向中介者注册参与者。成员方法sync()/syncToAll()将发起者的状态发送给其他的参与者。
interface ColleagueItf {
String getName();
String getStatus();
void setStatus(String status);
void syncStatus();
void syncStatusToColleague(String name);
}
interface MediatorItf {
void register(ColleagueItf participant);
void syncToAll(ColleagueItf sender);
void sync(ColleagueItf sender, String name);
}
ColleagueImpl类实现了ColleagueItf接口。ColleagueImpl类定义了一个status成员变量,用于保存目前的状态。成员变量mediator则指向中介者,用于将自身状态同步给其他同事。
public class ColleagueImpl implements ColleagueItf {
private String name = null;
private String status = null;
private MediatorItf mediator = null;
public ColleagueImpl(MediatorItf mediator, String name) {
this.name = name;
this.status = "Normal";
this.mediator = mediator;
}
@Override
public String getName() {
return this.name;
}
@Override
public String getStatus() {
return this.status;
}
@Override
public void setStatus(String status) {
this.status = status;
}
@Override
public void syncStatus() {
this.mediator.sync(this);
}
@Override
void syncStatusToColleague(String name) {
this.mediator.sync(this, name);
}
}
MediatorImpl类实现了接口MediatorItf。MediatorImpl使用成员变量participants维护着所有的参与者。成员方法register()向该对象添加新的参与者,而成员方法sync()/syncToAll()将状态通知给其他参与者。
import java.util.List;
import java.util.LinkedList;
public class MediatorImpl implements MediatorItf {
List<ColleagueItf> participants = new LinkedList<ColleagueItf>();
@Override
public void register(ColleagueItf participant) {
participants.add(participant);
}
@Override
public void syncToAll(ColleagueItf sender) {
String status = sender.getStatus();
for (ColleagueItf oneParticipant: participants) {
if (oneParticipant != sender)
sender.updateStatus(status);
}
}
@Override
public void sync(ColleagueItf sender, String name) {
String status = sender.getStatus();
for (ColleagueItf oneParticipant: participants) {
if (oneParticipant.getName().equals(name))
sender.updateStatus(status);
}
}
}
上述示例的使用方法如下。我们假设有三位老师共同教一门课。老师之间需要同步课程进度。由teacher1上第一节课,由teacher3上最后一节课。所以,在创建了Mediator对象和三位老师对象,并注册完毕之后,由第一位老师将课程状态更新为"Start",以便于通知所有老师课程开始了。在teacher3结束最后一节课之后,将状态更新为"Finish",用以通知所有老师课程结束了。
public class Course {
public static void main(String[] args) {
Mediator mediator = new MediatorImpl();
ColleagueItf teacher1 = new ColleagueImpl(mediator, "teacher1");
ColleagueItf teacher2 = new ColleagueImpl(mediator, "teacher2");
ColleagueItf teacher3 = new ColleagueImpl(mediator, "teacher3");
mediator.register(teacher1);
mediator.register(teacher2);
mediator.register(teacher3);
// 课程开始了
teacher1.setStatus("Start");
teacher1.syncStatusToColleague("teacher2");
// 继续上课 ...
// 课程结束了
teacher3.setStatus("Finish")
teacher3.syncStatus();
}
}
Java标准库中也使用了中介者模式。一个典型的用例是java.lang.reflect.Method。当调用invoke方法时,实际上,Java反射机制或者Method扮演者中介者的角色。调用者只需传入被调用的对象,而无需依赖于调用者。另外,java.util.Timer类的schedule()和java.util.concurrent.Executor的execute()方法也使用了中介者模式。在Timer类中,Timer有两个主要的功能。其一是等待超时事件的发生;其二是当超时时,运行一段程序。那么,这第二点实际上使用的是中介者模式,Timer扮演的是中介者。
本章介绍了中介者模式的结构和使用方法。它能够简化对象相互交互的复杂度,而且分离了相互交互的逻辑和对象内部的逻辑,因此,当对象相互交互的逻辑发生变化时,不会影响对象内部的逻辑。
注册用户登陆后可留言