中介者模式(Mediator Pattern)是行为设计模式之一,它允许减少对象之间的直接通信,从而降低系统的耦合度。下面我将介绍中介者模式的意图、结构以及适用性。
意图
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
- 封装一系列对象之间的交互。
- 使这些对象不需要显式地相互引用,让它们可以松散耦合。
- 可以独立地改变对象之间的交互。
结构
- Mediator(中介者):定义了一个接口用于与各Colleague(同事)对象通信。
- ConcreteMediator(具体中介者):实现 Mediator 接口,并协调 Colleague 对象之间的交互。
- Colleague(同事):每个同事只知道自己的行为,对于其他同事的行为一无所知,但它们都认识中介者对象。
- ConcreteColleague(具体同事):实现了 Colleague 的行为,并通过中介者与其他同事通信。
在这个结构图中:
Mediator
是中介者的接口,定义了用于同事间通信的方法。ConcreteMediator
是实现了Mediator
接口的具体中介者类,知道所有具体同事类,并协调它们之间的交互。Colleague
是同事的基类或接口,通常会持有对Mediator
的引用,并实现一些方法供其他同事通过中介者调用。Colleague1
和Colleague2
是具体的同事类,每个同事只知道自己的行为,对于其他同事的行为则一无所知,所有的交互都必须通过中介者来进行。
适用性
- 当一组对象以定义良好的方式相互通信时,你可以考虑使用中介者模式。中介者模式有助于封装这些交互。
- 如果你不希望某些对象直接引用其他对象,即你想解耦这些对象,那么中介者模式可以帮助实现这一点。
- 当你发现很难复用对象,因为它们紧密地联系在一起时,中介者模式可以用来分离这些对象,使得它们更容易被复用。
- 在系统中存在大量的对象间交互时,使用中介者模式可以简化对象间的通信,同时避免了对象间的强耦合。
实例
家庭系统多设备通讯
下面是一个简单的例子,假设我们有一个家庭自动化系统,其中包括多个设备如灯光、空调和音响。这些设备需要能够互相通信,比如当安全系统被触发时,灯光会亮起,空调关闭,音响发出警报声。如果没有使用中介者模式,每个设备之间都需要两两建立连接,这会导致系统非常复杂。使用中介者模式后,所有的设备只需要与一个中心控制器(中介者)通信即可。
首先,定义一个中介者的接口:
public interface Mediator {
void registerDevice(Device device);
void command(String command, Device sender);
}
接着,创建具体的中介者实现类:
import java.util.HashMap;
import java.util.Map;
public class HomeAutomationMediator implements Mediator {
private Map<String, Device> devices = new HashMap<>();
@Override
public void registerDevice(Device device) {
devices.put(device.getName(), device);
device.setMediator(this);
}
@Override
public void command(String command, Device sender) {
for (Map.Entry<String, Device> entry : devices.entrySet()) {
if (!entry.getKey().equals(sender.getName())) { // 不对自己发送命令
entry.getValue().executeCommand(command);
}
}
}
}
然后,定义设备的接口:
public interface Device {
String getName();
void setMediator(Mediator mediator);
void executeCommand(String command);
}
再创建一些具体设备的实现:
public class Light implements Device {
private Mediator mediator;
private String name;
public Light(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
@Override
public void executeCommand(String command) {
if ("ALARM".equals(command)) {
System.out.println("Light: Turning on the lights.");
} else if ("NORMAL".equals(command)) {
System.out.println("Light: Turning off the lights.");
}
}
}
// 其他设备如AirConditioner, Stereo等类似实现
最后,在客户端代码中配置并运行这个系统:
public class Client {
public static void main(String[] args) {
Mediator homeMediator = new HomeAutomationMediator();
Device light = new Light("Living Room Light");
Device airConditioner = new AirConditioner("Living Room AC");
Device stereo = new Stereo("Living Room Stereo");
homeMediator.registerDevice(light);
homeMediator.registerDevice(airConditioner);
homeMediator.registerDevice(stereo);
// 模拟外部事件,例如安全系统检测到入侵
light.executeCommand("ALARM");
}
}
在这个例子中,HomeAutomationMediator
充当了所有设备间的中介者,减少了设备之间的直接依赖。当有事件发生时(如执行"ALARM"
命令),相关的设备会接收到通知并做出响应。这种方式使得系统更易于扩展和维护。
聊天室
一个聊天室的例子。在这个例子中,多个用户(参与者)通过一个聊天室(中介者)进行交流。每个用户不需要知道其他用户的细节,他们只需要向聊天室发送消息,然后由聊天室负责将消息转发给所有在线的用户。
首先,定义中介者的接口:
public interface ChatRoom {
void register(User user);
void sendMessage(String message, User sender);
}
接着,创建具体的中介者实现类:
import java.util.ArrayList;
import java.util.List;
public class ConcreteChatRoom implements ChatRoom {
private List<User> users = new ArrayList<>();
@Override
public void register(User user) {
if (!users.contains(user)) {
users.add(user);
System.out.println(user.getName() + " has joined the chat.");
}
}
@Override
public void sendMessage(String message, User sender) {
for (User user : users) {
// 不对自己发送消息
if (user != sender) {
user.receive(message);
}
}
}
}
然后,定义参与者的接口:
public interface User {
String getName();
void receive(String message);
void send(String message, ChatRoom chatRoom);
}
再创建具体参与者的实现:
public class ConcreteUser implements User {
private String name;
private ChatRoom chatRoom;
public ConcreteUser(String name, ChatRoom chatRoom) {
this.name = name;
this.chatRoom = chatRoom;
chatRoom.register(this);
}
@Override
public String getName() {
return name;
}
@Override
public void receive(String message) {
System.out.println(name + " received: " + message);
}
@Override
public void send(String message, ChatRoom chatRoom) {
System.out.println(name + " sends: " + message);
chatRoom.sendMessage(message, this);
}
}
最后,在客户端代码中配置并运行这个系统:
public class Client {
public static void main(String[] args) {
ChatRoom chatRoom = new ConcreteChatRoom();
User john = new ConcreteUser("John", chatRoom);
User jane = new ConcreteUser("Jane", chatRoom);
User tom = new ConcreteUser("Tom", chatRoom);
john.send("Hello, everyone!", chatRoom);
jane.send("Hi, John! How are you?", chatRoom);
tom.send("Hey, what's up?", chatRoom);
}
}
在这个例子中,ConcreteChatRoom
作为中介者,它管理着所有用户,并在有新消息时负责将消息广播给所有其他用户。用户之间不再直接通信,而是通过聊天室间接地进行交流。这样做的好处是减少了用户间的耦合度,使得系统更加灵活和易于扩展。例如,如果以后需要添加新的功能,如私聊或者群聊,只需要修改中介者的逻辑即可,而无需改变用户类的代码。