概念

中介者模式(Mediator Pattern)是一种行为型设计模式,它通过引入一个中介者对象来封装一系列对象之间的交互,从而降低对象之间的耦合度


中介者模式通常涉及三个核心角色:中介者(Mediator)、同事对象(Colleague)和具体中介者(Concrete Mediator)

  • 中介者(Mediator)

    定义了一个接口用于与各个同事对象通信,并负责协调各个同事对象之间的交互

    中介者对象通常包含一个或多个方法,用于处理不同类型的交互事件

  • 同事对象(Colleague)

    各个参与交互的对象。同事对象可以向中介者发送消息,也可以接收来自中介者的消息

  • 具体中介者(Concrete Mediator)

    实现了中介者接口,负责实际的协调和控制各个同事对象之间的交互

    具体中介者对象通常包含了各个同事对象的引用,并根据收到的消息来进行相应的处理


中介者模式的核心思想是将系统中各个对象之间的交互行为集中到一个中介者对象中,从而降低对象之间的耦合度

这种模式的优点在于,可以减少对象之间的直接依赖关系,提高系统的灵活性和可维护性

中介者模式适用于以下情况:

  • 当系统中各个对象之间存在复杂的交互关系,并且希望将这些交互关系集中到一个对象中进行管理时,可以使用中介者模式
  • 当系统中的对象之间的交互关系随着系统的演化而变得复杂时,中介者模式也是一个很好的选择


举个简单的例子,考虑一个聊天室系统

聊天室中的用户可以发送消息给其他用户,而消息发送过程中需要对消息进行广播和接收等操作

中介者模式可以将聊天室对象视为一个中介者对象,负责管理用户之间的消息发送和接收

当用户发送消息时,可以将消息发送给聊天室对象,由聊天室对象负责将消息广播给所有在线用户

这样,可以实现用户之间的交互行为集中到一个中介者对象中进行管理,从而降低系统的复杂度


实现条件

  1. 存在多个对象之间的复杂交互

    中介者模式适用于存在多个对象之间的复杂交互,并且这些对象之间存在相互依赖的情况

  2. 需要解耦对象之间的关系

    中介者模式适用于需要解耦对象之间的关系,避免对象之间的直接通信,从而降低对象之间的耦合度

  3. 对象之间存在多对多的关系

    中介者模式适用于对象之间存在多对多的关系,并且对象之间的交互比较复杂的情况,通过引入中介者来统一管理对象之间的交互

  4. 需要集中化控制对象之间的交互

    中介者模式适用于需要集中化控制对象之间的交互,通过引入中介者来协调对象之间的交互,避免交互逻辑分散在多个对象中


优点

  1. 减少类之间的依赖关系

    中介者模式可以减少类之间的直接依赖关系,将对象之间的交互逻辑集中到中介者对象中,从而降低了类之间的耦合度

  2. 简化对象的交互

    中介者模式可以简化对象之间的交互逻辑,将复杂的交互逻辑封装到中介者对象中,使得对象之间只需要与中介者进行通信,而无需直接相互交互

  3. 提高系统的可维护性

    中介者模式将对象之间的交互逻辑集中到中介者对象中,使得系统的交互逻辑更加清晰和易于理解,从而提高了系统的可维护性

  4. 提高系统的灵活性

    中介者模式可以通过引入新的中介者对象来扩展系统的功能,而无需修改已有的对象,从而提高了系统的灵活性

  5. 降低了对象之间的直接耦合

    中介者模式可以避免对象之间的直接相互引用,降低了对象之间的耦合度,使得系统更加灵活和易于扩展


缺点

  1. 中介者对象可能变得复杂

    随着系统的演化,中介者对象可能会变得复杂,包含大量的交互逻辑,导致中介者对象变得难以维护和理解

  2. 可能导致单点故障

    如果中介者对象出现故障,可能会导致系统的其他部分无法正常工作,特别是系统的依赖性较高时

  3. 可能导致性能问题

    由于中介者对象负责管理对象之间的交互逻辑,可能会导致中介者对象成为系统的瓶颈,特别是在处理大量请求时可能会出现性能问题

  4. 增加了系统的复杂度

    中介者模式引入了一个额外的中介者对象,可能会增加系统的复杂度,特别是当系统中存在多个中介者对象时


实现方式

用户类与聊天室类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
* 表示聊天系统的用户。
*/
class User {
/**
* 创建一个User实例。
* @param {string} id - 用户的唯一标识符。
* @param {string} name - 用户的名称。
*/
constructor(id, name) {
this.id = id
this.name = name
this.chatRoom = null
}

/**
* 向当前聊天室发送消息。
* @param {string} message - 要发送的消息内容。
*/
sendMessage(message) {
if (this.chatRoom) {
this.chatRoom.sendMessage(this, message)
} else {
console.log('您还没有加入聊天室!')
}
}

/**
* 接收来自其他用户的消息。
* @param {string} message - 接收到的消息内容。
* @param {string} senderName - 发送者的名称。
*/
receive(message, senderName) {
console.log(`${this.name} 收到了来自 ${senderName} 的消息:${message}`)
}

/**
* 加入聊天室。
* @param {ChatRoom} chatRoom - 要加入的聊天室对象。
*/
joinChatRoom(chatRoom) {
if (chatRoom instanceof ChatRoom) { // 检查传入的是否是有效的ChatRoom实例
this.chatRoom = chatRoom
chatRoom.addUser(this)
} else {
console.error('提供的聊天室无效。')
}
}

/**
* 退出聊天室。
*/
leaveChatRoom() {
if (this.chatRoom) {
this.chatRoom.removeUser(this)
this.chatRoom = null
}
}

/**
* 获取用户名称。
* @returns {string} - 用户的名称。
*/
getName() {
return this.name
}
}

/**
* 表示一个聊天室,包含多个用户和消息传递功能。
*/
class ChatRoom {
/**
* 创建一个ChatRoom实例。
*/
constructor() {
this.users = new Map()
}

/**
* 添加用户到聊天室。
* @param {User} user - 要添加的用户对象。
*/
addUser(user) {
if (!this.users.has(user.id)) {
this.users.set(user.id, user)
console.log(`${user.getName()} 已加入聊天室。`)
} else {
console.warn(`ID为 ${user.id} 的用户已在聊天室中。`)
}
}

/**
* 从聊天室中移除用户。
* @param {User} user - 要移除的用户对象。
*/
removeUser(user) {
if (this.users.has(user.id)) {
const userName = user.getName()
this.users.delete(user.id)
console.log(`${userName} 已离开聊天室。`)
} else {
console.warn(`ID为 ${user.id} 的用户不在聊天室中。`)
}
}

/**
* 将消息广播给聊天室中的其他用户。
* @param {User} sender - 发送消息的用户对象。
* @param {string} message - 要发送的消息内容。
*/
sendMessage(sender, message) {
const senderName = sender.getName()
for (const [userId, user] of this.users) {
if (userId !== sender.id) {
user.receive(message, senderName)
}
}
}
}

// 导出User和ChatRoom类
export {
User,
ChatRoom
}


怎么使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 导入ChatRoom和User类
* 从'../MediatorPattern'路径导入ChatRoom和User类,用于创建聊天室和用户实例。
*/
import { ChatRoom, User } from '../MediatorPattern'

/**
* 创建一个聊天室实例
* 创建一个名为chatRoom的ChatRoom实例,作为用户交流的平台。
*/
const chatRoom = new ChatRoom()

/**
* 创建用户实例
* 创建三个不同的User实例,分别代表用户1、用户2和用户3。
*/
const user1 = new User('1', 'User 1')
const user2 = new User('2', 'User 2')
const user3 = new User('3', 'User 3')

/**
* 用户加入聊天室
* 将三个用户实例加入到chatRoom聊天室中,使他们能够进行通信。
*/
user1.joinChatRoom(chatRoom)
user2.joinChatRoom(chatRoom)
user3.joinChatRoom(chatRoom)

/**
* 用户发送消息
* 用户1和用户2分别向聊天室发送消息,演示了消息的发送过程。
*/
user1.sendMessage('Hello, everyone!')
user2.sendMessage('Hi, there!')


场景

  1. 聊天应用程序

    聊天室就是一个很好的中介者模式的应用场景

    用户通过聊天室发送和接收消息,而不需要直接与其他用户通信

  2. GUI 应用程序

    在复杂的 GUI 应用程序中,不同的组件可能需要相互通信,例如窗口、面板、按钮等

    中介者模式可以用来管理这些组件之间的通信,以减少耦合度

  3. 游戏开发

    在多人在线游戏中,玩家之间可能需要进行交互,例如发送消息、交易物品等

    中介者模式可以用来管理玩家之间的交互,以及处理游戏中的事件

  4. 交通系统

    在城市交通系统中,交通信号灯可以被视为中介者,管理交通流量并协调不同方向上的车辆行驶

    通过中介者模式,交通信号灯可以控制交通流量,避免交通拥堵和事故发生


源代码