中介者模式(Mediator pattern)顾名思义,就是充当了中介的角色,中介就是架起了消费者与开发商之间的桥梁,消费者无需知道开发商具体是谁,开发商也无须知道消费者具体是谁,他们都通过中介者来完成交易。
事实上,我们日常网上冲浪用到最多的微信也是如此。当我和朋友聊天的时候,严格意义上来说,我并不是和朋友在聊天,而是我将消息发送到聊天服务器这个“中介者”身上,然后聊天服务器将消息再转发给我的朋友。在这个过程中,我和我的朋友既是消息的发送者,也是消息的接收者。
1. 定义
中介者模式是一种行为型设计模式,它的定义是:“用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。”
2. 类图
在中介者模式中,有这样几种角色:
- 抽象中介者(Mediator):抽象中介者角色提供了同事角色的注册与响应方法,用于同事角色间的通信
- 具体中介者(Concrete Mediator):抽象中介者的实现类,聚合了一个列表来存储注册的同事类并对其进行管理
- 抽象同事类(Colleague):抽象同事角色会依赖抽象者角色,因为它会给予抽象者角色与其他同事角色进行通信,同时它会提供所有同事类的公有操作
- 具体同事类(Concrete Colleague):抽象同事类的实现类,实现了具体与其他同事角色的通信逻辑
中介者模式的类图如下:
3. 示例
今天就以一个简单的聊天服务器来介绍中介者模式,这里有两类角色,一个是聊天服务器,一个是用户,前者自然是中介者角色,那么后者就是同事角色。
下面来进行编码,首先定义同事角色,代码如下:
public class User {
// 用户昵称
private String username;
// 用户群组
private String group;
// 用户所属聊天服务器
private ChatServer chatServer;
public User(String username, String group) {
this.username = username;
this.group = group;
}
// 接收消息
public void receive(Message message) {
System.out.println("用户" + this.username + "收到用户" + message.getSender().getUsername() + "发来的消息,内容为:" + message.getContent());
}
// 发送消息
public void send(Message message) {
System.out.println("用户" + this.username + "向群组" + this.group + "的用户发出消息,内容为:" + message.getContent());
chatServer.reply(message);
}
// 省略 setter/getter 方法
}
同事角色有两个方法,一个是主动向中介者——聊天服务器发送消息的 send 方法;另一个是接收聊天服务器传递过来的信息的 receive 方法。
然后定义中介者角色,代码如下:
public class ChatServer {
private List<User> users = new ArrayList<>();
public void register(User user) {
users.add(user);
user.setChatServer(this);
System.out.println("用户" + user.getUsername() + "加入聊天室");
}
public void reply(Message message) {
for (User user1:users) {
if (message.getTargetGroup().equals(user1.getGroup())) {
user1.receive(message);
}
}
}
}
中介者角色会维护一个同事角色的列表,提供注册同事类方法和发送消息方法。
这里需要做一个消息体的抽象,代码如下所示:
public class Message {
// 发送内容
private String content;
// 发送组
private String targetGroup;
// 发送者
private User sender;
public Message(String content, String targetGroup, User sender) {
this.content = content;
this.targetGroup = targetGroup;
this.sender = sender;
}
// 省略 setter/getter 方法
}
最后编写测试代码:
public class Test {
public static void main(String[] args) {
ChatServer chatServer = new ChatServer();
User user1 = new User("user1", "A");
User user2 = new User("user2", "A");
User user3 = new User("user3", "B");
chatServer.register(user1);
chatServer.register(user2);
chatServer.register(user3);
Message message = new Message("你好", "A", user3);
user3.send(message);
}
}
输出结果为:
用户user1加入聊天室
用户user2加入聊天室
用户user3加入聊天室
用户user3向群组B的用户发出消息,内容为:你好
用户user1收到用户user3发来的消息,内容为:你好
用户user2收到用户user3发来的消息,内容为:你好
4. 使用场景
中介者模式的使用场景是:
- 在对象关系的类图中出现了复杂的网状结构时,可以考虑使用中介者模式
5. 小结
本文讲述了中介者模式,它的定义是——用一个中介对象封装一系列的对象交互,中介者使各对象不需要显示地相互作用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
中介者模式的优点是:
- 减少类与类之间的依赖与耦合度,如可以将原本一对多的关系优化为一对一,让系统变得易于维护
中介者模式的缺点是:
- 当同事类有很多时,中介者角色会变得十分复杂,难以维护
6. 参考资料
- 《设计模式之禅》(第2版)
- 中介者模式(详解版)
最后,本文收录于个人语雀知识库: 我所理解的后端技术,欢迎来访。
文档信息
- 本文作者:Planeswalker23
- 本文链接:https://planeswalker23.github.io/2022/02/22/%E6%88%91%E6%89%80%E7%90%86%E8%A7%A3%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E7%B3%BB%E5%88%97-%E7%AC%AC22%E7%AF%87-%E5%9F%BA%E4%BA%8E%E4%B8%AD%E4%BB%8B%E8%80%85%E6%A8%A1%E5%BC%8F%E5%AE%9E%E7%8E%B0%E8%81%8A%E5%A4%A9%E6%9C%8D%E5%8A%A1%E5%99%A8/
- 版权声明:本作品系原创,作者保留所有权利,未经作者允许,禁止转载和演绎。