一、概述
在软件设计中,对象之间的交互是不可避免的。然而,当对象之间的交互变得复杂时,系统的维护性和可扩展性往往会受到影响。为了解决这一问题,设计模式中的中介者模式(Mediator Pattern)应运而生。中介者模式是一种行为型设计模式,它通过一个中介者对象来封装一系列对象的交互,使得对象之间不必显式地相互引用,从而降低了对象之间的耦合度,提高了系统的灵活性和可维护性。中介者模式又叫调停模式,是迪米特法则(最少知识原则)的典型应用。
二、原理
在中介者模式中,各个对象不再直接相互引用和通信,而是通过中介者来进行间接通信。中介者负责协调各个对象之间的交互,降低了对象之间的耦合性,提高了系统的灵活性和可维护性。
中介者模式主要包括以下四种角色:
1、抽象中介者(Mediator)
定义了中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
2、具体中介者(ConcreteMediator)
实现中介者接口,定义一个集合来管理同事对象,协调各个同事角色之间的交互关系。
3、抽象同事类(Colleague)
定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
4、具体同事类(Concrete Colleague)
是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
三、功能
中介者模式的主要功能包括:
1、降低对象之间的耦合性
通过引入中介者,使得对象之间的直接依赖关系转变为对中介者的依赖,降低了对象之间的耦合性。
2、提高系统的灵活性
由于对象之间的交互被封装在中介者中,因此可以独立地改变对象之间的交互方式,而不需要修改对象本身的代码。
3、易于维护和扩展
由于对象之间的交互被中介者所管理,因此当需要增加新的交互或修改现有交互时,只需要修改中介者的代码即可,降低了系统的维护成本和扩展难度。
四、主要使用场景
1、中介者模式适用于以下场景:
1)、系统中对象之间存在复杂的引用关系
对象之间的依赖关系结构混乱且难以理解,通过引入中介者来封装对象之间的交互,可以降低系统的复杂性。
2)、一个对象引用了其他很多对象
并且直接和这些对象通信,导致难以复用该对象。通过引入中介者,可以将对象之间的交互封装在中介者中,使得对象可以更加独立地被复用。
3)、想通过一个中间类来封装多个类中的行为
而又不想生成太多的子类。中介者模式可以提供一个中介类来集中管理多个类之间的交互行为。
2、具体的应用场景包括:
1)、聊天室系统
可以使用中介者模式来管理用户之间的通信。
2)、航空管制系统
可以使用中介者模式来管理飞机之间的通信。
3)、MVC框架
在MVC框架中,控制器(Controller)可以作为模型(Model)和视图(View)之间的中介者。
4)、微服务架构
各服务通过一个API网关进行通信,API网关可以看作是一个中介者。
五、代码示例-Java
以下是一个简单的Java示例,模拟了一个聊天室场景,其中有多名用户(User)通过聊天室(ChatRoom,即中介者)进行通信。
java
// 定义中介者接口
public interface Mediator {
void sendMessage(String from, String to, String message);
void broadcastMessage(String from, String message);
}
// 实现中介者类(ChatRoom)
import java.util.ArrayList;
import java.util.List;
public class ChatRoom implements Mediator {
private List<User> users = new ArrayList<>();
@Override
public void sendMessage(String from, String to, String message) {
for (User user : users) {
if (user.getName().equals(to)) {
user.receiveMessage(from, message);
break;
}
}
}
@Override
public void broadcastMessage(String from, String message) {
for (User user : users) {
if (!user.getName().equals(from)) {
user.receiveMessage(from, message);
}
}
}
public void registerUser(User user) {
users.add(user);
user.setMediator(this);
}
}
// 定义用户类(User),它依赖于中介者进行通信
public class User {
private String name;
private Mediator mediator;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setMediator(Mediator mediator) {
this.mediator = mediator;
}
public void sendMessage(String to, String message) {
mediator.sendMessage(this.name, to, message);
}
public void broadcastMessage(String message) {
mediator.broadcastMessage(this.name, message);
}
public void receiveMessage(String from, String message) {
mediator.sendMessage(this.name, to, message);
}
}
// 客户端代码,用于演示如何使用这个中介者模式
public class Client {
public static void main(String[] args) {
ChatRoom chatRoom = new ChatRoom();
User alice = new User("Alice");
User bob = new User("Bob");
User charlie = new User("Charlie");
chatRoom.registerUser(alice);
chatRoom.registerUser(bob);
chatRoom.registerUser(charlie);
alice.sendMessage("Bob", "Hello Bob!");
charlie.broadcastMessage("Hello everyone!");
}
}
在这个例子中,ChatRoom是中介者,负责用户之间的消息传递。用户(User)通过中介者(ChatRoom)来发送和接收消息,而不需要直接与其他用户交互,从而降低了类之间的耦合度。
六、优缺点
1. 优点
降低了类的复杂度:
将一对多转化成了一对一,简化了对象之间的交互关系。
各个类之间的解耦:
通过引入中介者,使得对象之间的直接依赖关系转变为对中介者的依赖,降低了对象之间的耦合性。
符合迪米特原则:
即最少知识原则,每个对象只与直接相关的对象进行交互,减少了不必要的依赖。
2. 缺点
中介者可能会变得复杂:
当同事类数量较多时,中介者需要处理大量的交互逻辑,可能会导致中介者的代码变得复杂和难以维护。
中介者可能成为系统的瓶颈:
由于所有的交互都需要通过中介者来进行,因此中介者的性能可能会成为系统的瓶颈。
七、和代理模式的区别
中介者模式和代理模式是两种常见的设计模式,有一些类似但是主要区别如下:
1、目的和职责
中介者模式:
主要用于减少对象之间的相互耦合,通过引入一个中介对象来封装一系列对象之间的交互,使对象之间不必显式地相互引用,从而降低系统的复杂度,提高系统的灵活性和可维护性。中介者模式关注的是对象之间关系的处理,特别是当系统中存在多个对象之间复杂的交互关系时,使用中介者模式可以简化这些交互。
代理模式:
则是一种结构型设计模式,主要用于在访问对象时引入一定程度的间接性,从而可以附加多种用途,如进行权限控制、延迟加载、缓存等。代理模式关注的是结构方面的设计,它允许在不直接访问对象的情况下,通过一个代理对象来控制对该对象的访问。
2、通信方式
中介者模式:
在中介者模式中,多个对象之间的通信被集中到一个中介者对象中,这些对象通过中介者进行通信,而不是直接相互通信。因此,中介者模式通常呈现为多对多的通信关系。
代理模式:
在代理模式中,代理对象代表一个对象(即目标对象),客户端通过代理对象来访问目标对象。代理模式通常呈现为一对一的通信关系,即一个代理对象对应一个目标对象。
3、灵活性和扩展性
中介者模式:
由于中介者封装了对象之间的交互,当需要修改或扩展对象之间的交互时,只需修改中介者对象,而不需要修改各个对象的代码。这使得中介者模式具有较高的灵活性和扩展性。
代理模式:
代理模式同样具有一定的灵活性和扩展性,但它主要体现在对目标对象的访问控制上。通过代理对象,可以在调用目标方法前后添加额外的逻辑,如权限检查、日志记录等。然而,代理模式并不直接处理对象之间的交互关系。
4、实际应用场景
中介者模式:
适用于系统中存在多个对象之间复杂的交互关系时,如智能家庭管理系统中的设备通信、电商平台系统中的模块间通信等。在这些场景中,使用中介者模式可以简化对象之间的交互逻辑,降低系统的复杂度。
代理模式:
则更适用于需要对目标对象的访问进行控制或优化的场景,如远程访问、延迟加载、权限控制等。在这些场景中,代理对象作为客户端和目标对象之间的中间层,实现了对目标对象的间接访问和控制。
综上所述,中介者模式和代理模式在目的、职责、通信方式、灵活性和扩展性以及实际应用场景等方面都存在明显的区别。在软件设计中,应根据具体的需求和场景选择合适的设计模式来优化系统的结构和行为。
八、总结
在软件设计中,对象间的复杂交互常导致系统难以维护和扩展。中介者模式作为一种行为型设计模式,通过引入中介者对象来封装对象间的交互,降低了它们之间的直接依赖,从而提升了系统的灵活性和可维护性。此模式定义了四种角色:抽象中介者、具体中介者、抽象同事类和具体同事类。中介者模式的核心功能包括降低对象耦合性、提高系统灵活性以及简化维护和扩展。它适用于对象间存在复杂引用关系、一个对象引用众多其他对象,或希望通过中间类封装多个类行为的场景。具体应用场景如聊天室系统、航空管制系统、MVC框架和微服务架构中的API网关。尽管中介者模式能简化对象交互,但当同事类众多时,中介者可能变得复杂,甚至成为系统瓶颈。与代理模式相比,中介者模式关注对象间关系的处理,而代理模式则侧重于对目标对象的访问控制。