中介者模式
定义
用一个中介者来封装一系列的对象交互,这一系列对象不需要显示的互相引用,从而使其解耦合,而且可以独立的改变它们之间的交互。
结构
Mediator:抽象中介者,它定义了具体同事类交互的接口。
ConcreteMediator:具体中介者类,它持有所有具体同事类的引用,实现了抽象类中定义的接口,并且维护具体同事类之间交互的业务逻辑。
Colleague:抽象同事类,它持有抽象中介者类的引用,并在构造器中初始化值。
ConcreteColleague:具体同事类,它只知道自己的行为方法和中介者类,而不知道其他类的方法。
类图
抽象中介者类:
public abstract class Mediator {
public abstract void send(String message,Colleague colleague);
}
具体中介者类:
public class ConcreteMediator extends Mediator{
private ConcreteColleague1 colleague1;
private ConcreteColleague2 colleague2;
@Override
public void send(String message, Colleague colleague) {
if(colleague == colleague1){
colleague2.Notify(message);
}else{
colleague1.Notify(message);
}
}
public ConcreteColleague1 getColleague1() {
return colleague1;
}
public void setColleague1(ConcreteColleague1 colleague1) {
this.colleague1 = colleague1;
}
public ConcreteColleague2 getColleague2() {
return colleague2;
}
public void setColleague2(ConcreteColleague2 colleague2) {
this.colleague2 = colleague2;
}
}
抽象同事类:
public abstract class Colleague {
public Mediator mediator;
public Colleague(Mediator mediator){
this.mediator = mediator;
}
public Mediator getMediator() {
return mediator;
}
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
}
具体同事类1:
public class ConcreteColleague1 extends Colleague{
public ConcreteColleague1(Mediator mediator){
super(mediator);
}
public void send(String message){
mediator.send(message, this);
}
public void Notify(String message){
System.out.println("具体同事1收到消息:"+message);
}
}
具体同事类2:
public class ConcreteColleague2 extends Colleague{
public ConcreteColleague2(Mediator mediator){
super(mediator);
}
public void send(String message){
mediator.send(message, this);
}
public void Notify(String message){
System.out.println("具体同事2收到消息:"+message);
}
}
测试类:
public static void main(String[] args) {
ConcreteMediator cm = new ConcreteMediator();
ConcreteColleague1 c1 = new ConcreteColleague1(cm);
ConcreteColleague2 c2 = new ConcreteColleague2(cm);
cm.setColleague1(c1);
cm.setColleague2(c2);
c1.send("nice to meet you");
c2.send("nice to meet you too");
}
测试结果:
优点
1.具体同事类之间解耦合。
2.符合迪米特法则,如果两个对象需要互相调用可以通过第三方对象转发方法。
缺点
中介者对象需要处理各个具体同事类之间的交互逻辑,它的职责过多,不利于维护,并且不符合开闭原则,即对扩展开放,对修改封闭。
JDK类库中的中介者模式
java.util.Timer
请看下面的例子,timer是一个中介者,它持有新创建到TimerTask的引用,timer负责执行TimerTask的定时任务。
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("nice to meet u");
}
}, new Date(),1000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("nice to meet u too");
}
}, new Date(),1000);
java.util.concurrent.Executor#execute(Runnable command)
java.util.concurrent.ExecutorService#submit(Runnable command)
请看下面的例子,exec是一个中介者,它持有Runnable的引用,exec是一个异步任务执行者,它负责执行Runnable任务。
Executor exec = Executors.newFixedThreadPool(100);
exec.execute(new Runnable() {
@Override
public void run() {
System.out.println("nice to meet u");
}
});
exec.execute(new Runnable() {
@Override
public void run() {
System.out.println("nice to meet u too");
}
});
java.lang.reflect.Method#invoke(Obj obj,Object… args)
请看下面的例子,getName是一个中介者,,它持有User实例化对象的引用,它负责执行实例化对象的方法。
Class> clazz = Class.forName("com.headfirst.abstractfactorymode.dao.User");
User user1 = (User) clazz.newInstance();
User user2 = (User) clazz.newInstance();
user1.setName("zhangsan");
user2.setName("lisi");
Method getName = clazz.getMethod("getName");
Object invoke1 = getName.invoke(user1);
Object invoke2 = getName.invoke(user2);
System.out.println(invoke1);
System.out.println(invoke2);