调停者(Mediator)模式又称为中介者模式,包装了一系列对象相互作用的方式,使得这些对象不必互相明显引用。从而使它们可以较松散的耦合。当这些对象中的某些对象之间的相互作用发生变化时,不会立即影响到其他的一些对象之间的相互作用。从而保证这些相互作用可以彼此独立地变化。
0.中国加入WTO的例子
WTO是一个协调组织,各个贸易地区可以由WTO进行组织。WTO扮演的正是协调者的角色,它取代了原本由各个地区进行协调和谈判的强耦合关系,各个贸易地区加入世界贸易组织前的贸易状态如下:
WTO使得各个贸易地区之间的强关联关系变为较为松散的耦合关系, 各个贸易地区加入世界贸易组织的贸易状态如下:
1.结构
结构如下:
涉及到的角色如下:
抽象调停者(Mediator)角色:定义出同事对象到调停者对象的接口,其中主要方法是一个(或多个)事件方法。
具体调停者(ConcreteMediator)角色:实现了抽象调停者所声明的事件方法。具体调停者知晓所有的具体同事类,并负责具体的协调各同事对象的交互关系。
抽象同事类(Colleague)角色:定义出调停者到同事对象的接口。同事对象只知道调停者而不知道其余的同事对象。
具体同事类(ConcreteColleague)角色:所有的具体同事类均从抽象同事类继承而来。实现自己的业务,在需要与其他同事通信的时候,就与持有的调停者通信,调停者会负责与其他的同事交互。
源码如下:
抽象调停者:声明一个抽象方法colleagueChange,这就是所谓的事件方法。当自身的状态发生变化的时候,一个同事对象可以调用这个事件方法来通知调停者,从而更新有关的同事对象。
package mediator; /** * 抽象调停者 * */ public abstract class AbstractMediator { /** * 同事改变的时候通知调停者,调停者负责与其他同事交互 * * @param abstractColleague */ public abstract void colleagueChange(AbstractColleague abstractColleague); }
具体调停者:
package mediator; /** * 具体调停者 * */ public class ConcreteMediator extends AbstractMediator { private Colleague1 Colleague1; private Colleague2 Colleague2; @Override public void colleagueChange(AbstractColleague abstractColleague) { // 同事改变,协调其他同事类 } public void setColleague1(Colleague1 colleague1) { Colleague1 = colleague1; } public void setColleague2(Colleague2 colleague2) { Colleague2 = colleague2; } }
抽象同事类:声明一个action方法,当收到其他同事类改变后执行这个方法
package mediator; /** * 抽象同事 * */ public abstract class AbstractColleague { private AbstractMediator mediator; public AbstractColleague(AbstractMediator mediator) { super(); this.mediator = mediator; } /** * 具体的行动方法,由子类实现(商业方法) */ public abstract void action(); public void change() { mediator.colleagueChange(this); } public AbstractMediator getMediator() { return mediator; } }
具体同事类:每个同事仅知道调停者,无需知道其他同事
package mediator; /** * 具体同事类1 * */ public class Colleague1 extends AbstractColleague { public Colleague1(AbstractMediator mediator) { super(mediator); } @Override public void action() { // 执行操作 System.out.println("Colleague1 action"); // 通知调停者 getMediator().colleagueChange(this); } }
package mediator; /** * 具体同事类2 * */ public class Colleague2 extends AbstractColleague { public Colleague2(AbstractMediator mediator) { super(mediator); } @Override public void action() { // 执行操作 System.out.println("Colleague2 action"); // 通知调停者 getMediator().colleagueChange(this); } }
2.简单的聊天室案例
多个用户可以向聊天室发送消息,聊天室向所有的用户显示消息。我们将创建两个类 ChatRoom 和 User。User 对象使用 ChatRoom 方法来分享他们的消息。ChatRoom 就相当于调停者。
代码:
ChatRoom:
package mediator; import java.util.Date; public class ChatRoom { public static void showMessage(User user, String message) { System.out.println(new Date().toString() + " [" + user.getName() + "] : " + message); } }
User:
package mediator; public class User { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public User(String name) { this.name = name; } public void sendMessage(String message) { ChatRoom.showMessage(this, message); } }
测试类:
package mediator; public class Client { public static void main(String[] args) { User a = new User("A"); User b = new User("B"); a.sendMessage("Hi! B!"); b.sendMessage("Hello! A!"); } }
结果:
Mon Nov 04 14:35:51 CST 2019 [A] : Hi! B!
Mon Nov 04 14:35:51 CST 2019 [B] : Hello! A!
3.总结
调停者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。中介者模式属于行为型模式。
意图:用一个中介对象来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
主要解决:对象与对象之间存在大量的关联关系,这样势必会导致系统的结构变得很复杂,同时若一个对象发生改变,我们也需要跟踪与之相关联的对象,同时做出相应的处理。
何时使用:多个类相互耦合,形成了网状结构。
如何解决:将网状结构分离为星型结构。
关键代码:对象 Colleague 之间的通信封装到一个类中单独处理。
应用实例: 1、中国加入 WTO 之前是各个国家相互贸易,结构复杂,现在是各个国家通过 WTO 来互相贸易。 2、机场调度系统。 3、MVC 框架,其中C(控制器)就是 M(模型)和 V(视图)的中介者。
优点: 1、降低了类的复杂度,将一对多转化成了一对一。 2、各个类之间的解耦。 3、符合迪米特原则。
缺点:中介者会庞大,变得复杂难以维护。
使用场景: 1、系统中对象之间存在比较复杂的引用关系,导致它们之间的依赖关系结构混乱而且难以复用该对象。 2、想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。
注意事项:不应当在职责混乱的时候使用。