为什么需要中介者模式?
假设在设计一个智能家居系统家里有空调、窗帘、灯三种设备。业务规则是空调开启时自动关闭窗帘避免冷气流失窗帘关闭时自动开灯补充采光。最直觉的写法是让设备之间直接互相调用class AirConditioner { private Curtain curtain; private Light light; public void turnOn() { // 空调开启逻辑 curtain.close(); // 直接调用窗帘 } } class Curtain { private Light light; public void close() { // 窗帘关闭逻辑 light.turnOn(); // 直接调用灯 } }这种写法的问题很快暴露空调需要知道窗帘窗帘需要知道灯设备之间形成复杂的网状依赖。如果新增一个设备如加湿器需要修改所有相关设备的代码。更麻烦的是如果业务规则变了比如空调开启时也要开灯就得改空调的代码违反开闭原则。中介者模式解决的就是这种多个对象之间存在复杂联动关系的耦合问题。把所有联动规则集中到一个中介者对象里设备只跟中介者通信互不认识。概念中介者模式Mediator Pattern是一种行为型设计模式核心思想是用一个中介对象封装一系列对象之间的交互使各对象不需要显式地互相引用从而使其耦合松散而且可以独立改变它们之间的交互。可以把它想象成航空管制塔台每架飞机同事对象不需要知道其他飞机的位置和航线只需要向塔台中介者报告自己的状态塔台根据全局信息协调所有飞机的起降和飞行路径。飞机之间互不通信全部通过塔台协调。中介者模式涉及四个角色Mediator抽象中介者定义中介者接口用于各同事对象之间的通信ConcreteMediator具体中介者实现中介者接口负责协调各同事对象的交互关系需要知道所有同事类Colleague抽象同事类定义同事类接口维护一个对中介者对象的引用ConcreteColleague具体同事类实现同事类接口每个同事类只知道自己行为通过中介者与其他同事交互实现继承继承持有同事列表持有中介者引用«interface»Mediatorregister(colleague: Colleague)send(message: String, colleague: Colleague)ConcreteMediator-colleagues: ListColleagueregister(colleague: Colleague)send(message: String, colleague: Colleague)«abstract»Colleague#mediator: Mediatorsend(message: String)receive(message: String)ConcreteColleagueAsend(message: String)receive(message: String)ConcreteColleagueBsend(message: String)receive(message: String)图中各类之间的关系Mediator接口定义了register和send方法ConcreteMediator实现该接口并持有ListColleagueColleague抽象类持有Mediator引用并通过它发送消息——同事类之间不直接通信全部通过中介者协调。实现GoF 的标准实现中中介者维护所有同事的引用同事通过中介者转发消息。当同事状态变化时通知中介者中介者根据业务规则决定通知哪些其他同事。标准实现定义一个Mediator接口作为抽象中介者声明register注册同事和send转发消息方法。Colleague作为抽象同事类持有中介者引用提供send发送消息和receive接收消息方法。具体中介者ConcreteMediator维护同事列表在send方法中实现消息转发策略。具体同事类ConcreteColleagueA和ConcreteColleagueB通过中介者与其他同事交互。// 抽象中介者 interface Mediator { public void register(Colleague colleague); public void send(String message, Colleague colleague); } // 抽象同事类 abstract class Colleague { protected Mediator mediator; public Colleague(Mediator mediator) { this.mediator mediator; } public abstract void receive(String message); public abstract void send(String message); } // 具体中介者 class ConcreteMediator implements Mediator { private ListColleague colleagues new ArrayList(); public void register(Colleague colleague) { colleagues.add(colleague); } public void send(String message, Colleague colleague) { // 转发给除发送者外的所有同事 for (Colleague c : colleagues) { if (c ! colleague) { c.receive(message); } } } } // 具体同事类A class ConcreteColleagueA extends Colleague { public ConcreteColleagueA(Mediator mediator) { super(mediator); } public void receive(String message) { System.out.println(ColleagueA 收到消息: message); } public void send(String message) { System.out.println(ColleagueA 发送消息: message); mediator.send(message, this); } } // 具体同事类B class ConcreteColleagueB extends Colleague { public ConcreteColleagueB(Mediator mediator) { super(mediator); } public void receive(String message) { System.out.println(ColleagueB 收到消息: message); } public void send(String message) { System.out.println(ColleagueB 发送消息: message); mediator.send(message, this); } }角色对照Mediator抽象中介者Mediator接口定义register和send方法ConcreteMediator具体中介者ConcreteMediator维护同事列表实现消息转发策略Colleague抽象同事类Colleague抽象类持有中介者引用提供send和receive方法ConcreteColleague具体同事类ConcreteColleagueA、ConcreteColleagueB通过中介者与其他同事交互关键点同事类只负责自身状态通过中介者转发消息中介者维护所有同事引用根据业务规则决定消息转发策略。同事之间不直接通信全部通过中介者协调。引入一个具体场景智能家居系统空调、窗帘、灯三种设备通过中控中介者协调联动。空调开启时自动关闭窗帘避免冷气流失窗帘关闭时自动开灯补充采光。// 抽象中介者 interface SmartHomeMediator { public void register(Device device); public void notify(String event, Device device); } // 抽象同事类设备基类 abstract class Device { protected SmartHomeMediator mediator; protected String name; protected boolean state; public Device(SmartHomeMediator mediator, String name) { this.mediator mediator; this.name name; this.state false; } public String getName() { return name; } public boolean getState() { return state; } public void setState(boolean state) { this.state state; System.out.println(name (state ? 开启 : 关闭)); mediator.notify(state ? on : off, this); } public abstract void handleEvent(String event); } // 具体中介者智能家居中控 class ConcreteSmartHomeMediator implements SmartHomeMediator { private ListDevice devices new ArrayList(); public void register(Device device) { devices.add(device); } public void notify(String event, Device device) { // 空调开启 → 关闭窗帘 if (device instanceof AirConditioner event.equals(on)) { for (Device d : devices) { if (d instanceof Curtain) { d.setState(false); } } } // 窗帘关闭 → 开启灯 if (device instanceof Curtain event.equals(off)) { for (Device d : devices) { if (d instanceof Light) { d.setState(true); } } } } } // 具体同事类空调 class AirConditioner extends Device { public AirConditioner(SmartHomeMediator mediator) { super(mediator, 空调); } public void handleEvent(String event) { // 空调不处理其他设备的事件 } } // 具体同事类窗帘 class Curtain extends Device { public Curtain(SmartHomeMediator mediator) { super(mediator, 窗帘); } public void handleEvent(String event) { // 窗帘不处理其他设备的事件 } } // 具体同事类灯 class Light extends Device { public Light(SmartHomeMediator mediator) { super(mediator, 灯); } public void handleEvent(String event) { // 灯不处理其他设备的事件 } }角色对照Mediator抽象中介者SmartHomeMediator接口定义register和notify方法ConcreteMediator具体中介者ConcreteSmartHomeMediator维护设备列表实现联动规则Colleague抽象同事类Device抽象类持有中介者引用状态变化时通知中介者ConcreteColleague具体同事类AirConditioner、Curtain、Light具体设备实现关键点设备状态变化时调用setState在setState中通知中介者中介者根据事件类型和设备类型执行联动规则如果业务规则变化比如空调开启时也要开灯只需修改中介者的notify方法设备类不变。总结本质用一个中介对象封装多个对象之间的交互将网状依赖转化为星形结构。什么时候用多个对象之间存在复杂的网状依赖关系需要集中管理对象间的交互规则想要降低对象间的耦合度提高可维护性什么时候不用对象之间只有简单的两两交互引入中介者反而增加复杂度性能要求极高中介者转发消息的开销不可接受中介者本身会变得过于庞大复杂上帝对象简单记忆中介者管协调同事只管报规则集中改耦合自然少。