Mediator中介者模式:当多个对象彼此间都有联系时,可应用Mediator将对象间的多对多关系转换为一对多的关系,使各个对象间的耦合松散,统一管理对象间的交互。 使用场景:一组对象以定义良好但复杂方式进行通信,产生了混乱的依赖关系,导致对象难以复用时,用中介者模式集中负责维护对象模型的关系完整性,封装对象间交互方式。如MVC中的controller就是Mediator,是UI层和后端应用sevice层间的中介者,中介者将交互的复杂性变为中介者的复杂性。 一、组成角色 1、抽象中介者(Mediator)角色:抽象中介者角色定义统一的接口用于各同事角色之间的通信。 2、具体中介者(Concrete Mediator)角色:具体中介者角色通过协调各同事角色实现协作行为。为此它要知道并引用各个同事角色。 3、同事(Colleague)角色:每一个同事角色都知道对应的具体中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。 二、类图
由于中介者的行为与要使用的数据、具体业务紧密相关,抽象中介者角色提供一个能方便很多对象使用的接口是不太现实的。所以抽象中介者角色往往不存在或只是一个标识接口。 使用中介者模式好处就是将同事角色解耦。改善系统结构,提高系统可读性、简化系统通信协议(将多对多变为一对多)、提高了代码的可复用性。 但也可能使Mediator对象成为一个系统中的庞然大物,难以维护,所以注意控制中介者角色的大小。 中介者模式很容易应用,也很容易误用。当出现了多对多交互的对象群,首先确认系统统在设计上是不是合理再使用中介者模式。 三、实现 1、交互对象的抽象类Colleague package com.makocn.javapatterns.mediator; public abstract class Colleague { private Mediator mediator; private String message; public Mediator getMediator() { return mediator; } public Colleague(Mediator m) { mediator = m; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public void sendMessage(String message) { this.message = message; mediator.action(this); } public abstract void sendMessage(); public abstract void getMessage(String message); } 2、中介者接口Mediator package com.makocn.javapatterns.mediator; public interface Mediator { //Mediator针对Colleague的一个交互行为 public void action(Colleague sender); //加入Colleague对象 public void addCollegue(Colleague colleague); } 3、具体中介类ConcreteMediator package com.makocn.javapatterns.mediator; import java.util.ArrayList; import java.util.List; public class ConcreteMediator implements Mediator { private List<Colleague> colleagues = new ArrayList<Colleague>(0); public void addCollegue(Colleague colleague) { colleagues.add(colleague); } public void action(Colleague actor) { String msg = actor.getMessage(); for (Colleague colleague : colleagues) { if (colleague.equals(actor)) { colleague.sendMessage(); break; } } for (Colleague colleague : colleagues) { if (colleague.equals(actor)) continue; colleague.getMessage(msg); } } } 4、交互对象的实现类Colleague1、Colleague2 package com.makocn.javapatterns.mediator; public class Colleague1 extends Colleague { public Colleague1(Mediator m) { super(m); } public void getMessage(String message) { System.out.println("Colleague1 has got the message -'" + message + "'"); } public void sendMessage() { System.out.println("Colleague1 has send the message '" + getMessage() + "'"); } } package com.makocn.javapatterns.mediator; public class Colleague2 extends Colleague { public Colleague2(Mediator m) { super(m); } public void getMessage(String message) { System.out.println("Colleague2 has got the message -'" + message + "'"); } public void sendMessage() { System.out.println("Colleague2 has send the message '" + getMessage() + "'"); } } 5、客户端测试类MediatorClient package com.makocn.javapatterns.mediator; public class MediatorClient { public static void main(String[] args) { // 生成中介者并注入到各个Colleague对象中 Mediator mediator = new ConcreteMediator(); Colleague colleague1 = new Colleague1(mediator); Colleague colleague2 = new Colleague2(mediator); // 注册对象到中介 mediator.addCollegue(colleague1); mediator.addCollegue(colleague2); // Colleague1 触发行为 colleague1.sendMessage("Hi,it's time to lunch. Let's go!"); System.out.println(); // Colleague2 触发行为 colleague2.sendMessage("Is anybody here!"); System.out.println(); } } 四、与其他模式比较 在结构上,中介者模式与观察者模式、命令模式都添加了中间对象,中介者去掉了后两者在行为上的方向。因此中介者的应用可以仿照后两者的例子去写。但是观察者模式、命令模式中的观察者、命令都被客户所知,具体的观察者、命令的应用都由客户来指定的;而大多中介者角色对于客户程序却是透明的。造成这种区别的原因是要达到的目的不同。 从目的上看,中介者模式与门面模式有些相似,但是门面模式是介于客户程序与子系统之间,而中介者模式是介于子系统与子系统之间。门面模式是将原有的复杂逻辑提取到一个统一的接口,简化客户对逻辑的使用,它是被客户所感知的。而中介者模式的加入并没有改变客户原有的使用习惯,它是隐藏在原有逻辑后面的,使得代码逻辑更加清晰可用。