2025/10/15日 每日总结 设计模式实践:中介者模式之虚拟聊天室案例解析
设计模式实践:中介者模式之虚拟聊天室案例解析
在多对象交互频繁的场景中,对象间直接耦合会导致系统复杂度飙升、维护困难。中介者模式通过引入“中介者”角色,让所有对象通过中介者间接通信,从而降低对象间的直接耦合,将复杂的多对多关系转化为简单的一对多关系。本文将通过带限制条件的虚拟聊天室案例,详细拆解中介者模式的实现逻辑与应用价值。
一、实验背景与需求
本次实践的核心需求是扩展虚拟聊天室功能,新增带限制的聊天室和增强型会员,具体要求如下:
-
新聊天室规则:文本消息长度≤100字符,图片大小≤20MB(超出则拦截并提示)
-
新会员能力:支持发送文本消息(自动添加时间戳)和图片消息
-
核心约束:会员间不直接通信,所有消息通过聊天室(中介者)转发
-
保留原有功能:支持会员加入/退出、聊天记录存储与打印
二、中介者模式核心结构
中介者模式的关键在于“中介者”统一管理对象交互逻辑,“同事类”仅与中介者通信,不直接交互。本次案例的结构设计如下:
1. 核心组件划分
| 组件类型 | 具体实现 | 职责描述 |
|---|---|---|
| 抽象中介者 | ChatRoom(抽象聊天室) | 定义中介者核心接口,维护同事类(会员)列表,声明消息转发方法 |
| 具体中介者 | ConcreteChatRoom(具体聊天室) | 实现消息/图片发送逻辑,添加长度/大小限制,存储聊天记录 |
| 抽象同事类 | Member(抽象会员) | 定义会员的基本接口(发送消息),存储会员名称 |
| 具体同事类 | ConcreteMember(具体会员) | 实现发送文本(带时间戳)和图片的功能,通过中介者转发消息 |
2. 类图结构
┌─────────────────┐
│ ChatRoom │ ← 抽象中介者(聊天室)
├─────────────────┤
│ - members: List<Member> │ ← 维护会员列表
│ - messages: List<String> │ ← 存储聊天记录
├─────────────────┤
│ + addMember(member: Member): void │ ← 添加会员
│ + removeMember(member: Member): void │ ← 移除会员
│ + abstract sendMessage(sender: Member, msg: String): void │ ← 转发文本消息(抽象)
└─────────────────┘
▲
│
┌───────────────┐
│ConcreteChatRoom│ ← 具体中介者(带限制的聊天室)
├───────────────┤
│ - MAX_TEXT_LENGTH: int = 100 │ ← 文本长度限制
│ - MAX_IMAGE_SIZE: int = 20MB │ ← 图片大小限制
├───────────────┤
│ + sendMessage(sender: Member, msg: String): void │ ← 实现文本发送(含长度校验)
│ + sendImage(sender: Member, image: byte[]): void │ ← 新增图片发送(含大小校验)
│ + printMessages(): void │ ← 打印聊天记录
└───────────────┘
▲
│
┌─────────────────┐
│ Member │ ← 抽象同事类(会员)
├─────────────────┤
│ - name: String │ ← 会员名称
├─────────────────┤
│ + Member(name: String) │
│ + getName(): String │
│ + abstract sendMessage(msg: String): void │ ← 发送文本消息(抽象)
└─────────────────┘
▲
│
┌───────────────┐
│ConcreteMember │ ← 具体同事类(增强型会员)
├───────────────┤
│ - chatRoom: ConcreteChatRoom │ ← 持有中介者引用
├───────────────┤
│ + ConcreteMember(name: String, chatRoom: ConcreteChatRoom) │ ← 构造时自动加入聊天室
│ + sendMessage(msg: String): void │ ← 发送带时间戳的文本
│ + sendImage(image: byte[]): void │ ← 发送图片
└───────────────┘
三、完整实现代码(Java)
1. 抽象中介者:ChatRoom.java
import java.util.ArrayList;
import java.util.List;
/**
* 抽象聊天室类 - 中介者核心接口
*/
abstract class ChatRoom {
// 维护聊天室会员列表
protected List<Member> members = new ArrayList<>();
// 存储聊天记录
protected List<String> messages = new ArrayList<>();
// 添加会员到聊天室
public void addMember(Member member) {
members.add(member);
}
// 从聊天室移除会员
public void removeMember(Member member) {
members.remove(member);
}
// 转发文本消息(抽象方法,由具体聊天室实现)
public abstract void sendMessage(Member sender, String message);
}
2. 具体中介者:ConcreteChatRoom.java
/**
* 具体聊天室 - 带限制的中介者实现
*/
class ConcreteChatRoom extends ChatRoom {
// 文本消息最大长度(100字符)
private static final int MAX_TEXT_LENGTH = 100;
// 图片最大大小(20MB = 20*1024*1024 字节)
private static final int MAX_IMAGE_SIZE = 20 * 1024 * 1024;
@Override
public void sendMessage(Member sender, String message) {
// 校验文本长度
if (message.length() > MAX_TEXT_LENGTH) {
System.out.println("消息内容超出最大字数限制(100字符)!");
return;
}
// 存储聊天记录(含发送者)
String fullMessage = sender.getName() + ": " + message;
messages.add(fullMessage);
System.out.println("发送成功: " + fullMessage);
}
// 新增:发送图片(含大小校验)
public void sendImage(Member sender, byte[] image) {
if (image.length > MAX_IMAGE_SIZE) {
System.out.println("图片大小超出最大限制(20MB)!");
return;
}
System.out.println(sender.getName() + " 发送了一张图片");
}
// 打印所有聊天记录
public void printMessages() {
System.out.println("\n=== 聊天记录 ===");
for (String msg : messages) {
System.out.println(msg);
}
}
}
3. 抽象同事类:Member.java
/**
* 抽象会员类 - 同事类接口
*/
abstract class Member {
protected String name;
// 构造函数:初始化会员名称
public Member(String name) {
this.name = name;
}
// 获取会员名称
public String getName() {
return name;
}
// 发送文本消息(抽象方法,由具体会员实现)
public abstract void sendMessage(String message);
}
4. 具体同事类:ConcreteMember.java
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 具体会员类 - 支持文本(带时间戳)和图片发送
*/
class ConcreteMember extends Member {
// 持有中介者(聊天室)引用,仅与中介者通信
private ConcreteChatRoom chatRoom;
// 构造函数:创建时自动加入聊天室
public ConcreteMember(String name, ConcreteChatRoom chatRoom) {
super(name);
this.chatRoom = chatRoom;
this.chatRoom.addMember(this);
}
@Override
public void sendMessage(String message) {
// 新增:文本消息添加时间戳
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStamp = sdf.format(new Date());
String messageWithTime = message + " (发送时间: " + timeStamp + ")";
// 不直接发送,通过中介者转发
chatRoom.sendMessage(this, messageWithTime);
}
// 新增:发送图片
public void sendImage(byte[] image) {
chatRoom.sendImage(this, image);
}
}
### 5. 客户端测试类:Main.java
```java
/**
* 测试类:验证聊天室功能(文本/图片发送、限制校验、聊天记录)
*/
public class Main {
public static void main(String[] args) {
// 1. 创建中介者(带限制的聊天室)
ConcreteChatRoom chatRoom = new ConcreteChatRoom();
// 2. 创建同事类(会员),自动加入聊天室
ConcreteMember alice = new ConcreteMember("Alice", chatRoom);
ConcreteMember bob = new ConcreteMember("Bob", chatRoom);
// 3. 测试1:发送正常文本消息(带时间戳)
System.out.println("=== 正常文本测试 ===");
alice.sendMessage("你好,这是中介者模式实现的聊天室!");
bob.sendMessage("Hi Alice,我能发送带时间戳的消息~");
// 4. 测试2:发送超长文本(触发限制)
System.out.println("\n=== 超长文本测试 ===");
String longMsg = "这是一条超过100字符的测试消息,用来验证聊天室的文本长度限制功能。设计模式真的很有用,中介者模式能帮我们解耦对象间的交互,让代码更易维护!";
alice.sendMessage(longMsg);
// 5. 测试3:发送正常大小图片(15MB)
System.out.println("\n=== 正常图片测试 ===");
byte[] normalImage = new byte[15 * 1024 * 1024]; // 15MB
alice.sendImage(normalImage);
// 6. 测试4:发送超大图片(25MB,触发限制)
System.out.println("\n=== 超大图片测试 ===");
byte[] largeImage = new byte[25 * 1024 * 1024]; // 25MB
bob.sendImage(largeImage);
// 7. 测试5:打印聊天记录
chatRoom.printMessages();
}
}
四、运行结果
=== 正常文本测试 ===
发送成功: Alice: 你好,这是中介者模式实现的聊天室! (发送时间: 2024-05-20 14:30:45)
发送成功: Bob: Hi Alice,我能发送带时间戳的消息~ (发送时间: 2024-05-20 14:30:46)
=== 超长文本测试 ===
消息内容超出最大字数限制(100字符)!
=== 正常图片测试 ===
Alice 发送了一张图片
=== 超大图片测试 ===
图片大小超出最大限制(20MB)!
=== 聊天记录 ===
Alice: 你好,这是中介者模式实现的聊天室! (发送时间: 2024-05-20 14:30:45)
Bob: Hi Alice,我能发送带时间戳的消息~ (发送时间: 2024-05-20 14:30:46)
五、中介者模式核心优势与特性
1. 核心优势
-
解耦对象交互:会员间无需知道彼此存在,所有通信通过聊天室转发,避免多对多直接耦合
-
集中管理逻辑:文本长度、图片大小等限制规则集中在聊天室,修改时无需改动会员类,维护更高效
-
扩展性强:新增功能(如消息撤回、@某人)只需修改中介者,或新增中介者子类,符合开闭原则
-
简化对象职责:会员仅需关注“发送消息”,无需处理消息校验、转发等逻辑,职责单一
2. 适用场景与注意事项
适用场景
-
多对象间交互频繁,形成复杂网络(如聊天室、即时通讯、工作流系统)
-
需统一管理交互规则(如权限校验、格式限制、日志记录)
-
希望降低对象耦合,提高系统可维护性
注意事项
-
中介者可能成为“上帝类”:需合理拆分逻辑,避免中介者过于庞大
-
适合交互规则相对稳定的场景:若规则频繁变化,中介者可能频繁修改
-
避免过度使用:简单的对象交互无需引入中介者,否则会增加系统复杂度
六、总结
通过本次虚拟聊天室的实践案例,深刻体会到中介者模式在解耦多对象交互中的核心价值。它将分散在各个对象中的交互逻辑集中到中介者,让对象专注于自身核心职责,同时让系统结构更清晰、维护更便捷。
在实际开发中,除了聊天室,中介者模式还广泛应用于电商订单流程(订单、支付、库存、物流通过订单管理器协调)、团队协作工具(成员通过平台交互)等场景。合理运用中介者模式,能有效解决多对象耦合带来的维护难题。

浙公网安备 33010602011771号