中介者模式通过引入中介类降低对象间耦合度,在电商平台中,卖家、买家、物流公司和支付平台原本需复杂交互,在引入"交易中介"类后,各角色只需与中介交互,由中介协调各方操作,从而简化了交互流程,降低了类间依赖,使系统更灵活可维护。
定义
中介者模式主要用于减少类之间的耦合,它用一个中介类来封装一系列对象间的交互,使这些对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
举一个业务中的例子来说明,假设有一个电商平台,其中有卖家、买家、物流公司和支付平台四个角色,在没有中介者的情况下,这四个角色之间可能需要进行复杂的交互,比如卖家要直接联系物流公司发货,买家要直接联系支付平台进行支付等,这样的设计会导致类之间的耦合度很高,一旦某个角色发生变化,可能会影响到其他角色。
而引入中介者模式后,可以设计一个电商平台的"交易中介"类,这个类中介了卖家、买家、物流公司和支付平台之间的所有交互,卖家只需要将商品信息和买家信息提交给交易中介,交易中介会负责联系物流公司进行发货,并通知买家进行支付,买家支付完成后,交易中介会通知卖家和物流公司更新订单状态,这样,卖家、买家、物流公司和支付平台之间的耦合度就大大降低了,每个角色只需要和交易中介进行交互,而不需要直接和其他角色进行交互。
在这个场景中中,交易中介类就起到了中介者的作用,它将一系列对象间的交互封装起来,使这些对象之间的耦合度降低,提高了系统的灵活性和可维护性。
代码案例
反例
下面是一个未使用中介者模式的反例代码,假如,有一个聊天应用的简单模型,其中包括User
(用户)和GroupChat
(群聊)类,每个User
对象都直接与其他User
对象通信,如下代码演示:
java
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void sendMessage(User receiver, String message) {
System.out.println(name + " sends a message to " + receiver.getName() + ": " + message);
}
}
public class GroupChat {
private List<User> users = new ArrayList<>();
public void addUser(User user) {
users.add(user);
}
public void notifyAllUsers(String message) {
for (User user : users) {
for (User otherUser : users) {
if (!user.equals(otherUser)) {
user.sendMessage(otherUser, message);
}
}
}
}
}
public class Client {
public static void main(String[] args) {
User alice = new User("Alice");
User bob = new User("Bob");
User charlie = new User("Charlie");
GroupChat chat = new GroupChat();
chat.addUser(alice);
chat.addUser(bob);
chat.addUser(charlie);
alice.sendMessage(bob, "Hi Bob, how are you?");
alice.sendMessage(charlie, "Hi Charlie, what's up?");
chat.notifyAllUsers("Everyone, there will be a maintenance tonight.");
}
}
输出结果,如下:
java
Alice sends a message to Bob: Hi Bob, how are you?
Alice sends a message to Charlie: Hi Charlie, what's up?
Alice sends a message to Bob: Everyone, there will be a maintenance tonight.
Alice sends a message to Charlie: Everyone, there will be a maintenance tonight.
Bob sends a message to Alice: Everyone, there will be a maintenance tonight.
Bob sends a message to Charlie: Everyone, there will be a maintenance tonight.
Charlie sends a message to Alice: Everyone, there will be a maintenance tonight.
Charlie sends a message to Bob: Everyone, there will be a maintenance tonight.
在这个反例中,User
类直接持有对其他User
对象的引用,并直接调用其方法,这导致了类之间的紧密耦合,因为User
类需要知道如何与其他User
对象通信,此外,GroupChat
类虽然被设计出来,但并没有起到中介消息的作用,实际上,当notifyAllUsers
方法被调用时,每个用户都会向其他每个用户发送消息,导致了重复的消息和不必要的复杂性。
正例
下面是一个使用中介者模式的正例代码,在这个例子中,有一个聊天应用的模型,包括User
(用户)和ChatMediator
(聊天中介)类,ChatMediator
类作为中介者,封装了用户之间的通信逻辑,使得用户之间不需要直接相互引用,如下代码:
java
import java.util.*;
// User.java
public class User {
private String name;
private ChatMediator chatMediator;
public User(String name, ChatMediator chatMediator) {
this.name = name;
this.chatMediator = chatMediator;
}
public String getName() {
return name;
}
// 用户通过中介者发送消息
public void sendMessage(String receiverName, String message) {
chatMediator.relayMessage(this, receiverName, message);
}
}
// ChatMediator.java
public class ChatMediator {
private Map<String, User> users = new HashMap<>();
public void registerUser(User user) {
users.put(user.getName(), user);
}
// 中介者负责将消息传递给指定的接收者
public void relayMessage(User sender, String receiverName, String message) {
User receiver = users.get(receiverName);
if (receiver != null) {
System.out.println(sender.getName() + " sends a message to " + receiver.getName() + ": " + message);
// 这里可以添加额外的逻辑,比如记录消息、通知其他服务等
} else {
System.out.println("Receiver " + receiverName + " is not online.");
}
}
}
// 客户端代码
public class Client {
public static void main(String[] args) {
// 创建中介者和用户
ChatMediator chatMediator = new ChatMediator();
User alice = new User("Alice", chatMediator);
User bob = new User("Bob", chatMediator);
// 用户注册到中介者
chatMediator.registerUser(alice);
chatMediator.registerUser(bob);
// Alice通过中介者发送消息给Bob
alice.sendMessage("Bob", "Hi Bob, how are you?");
// Bob通过中介者回复消息给Alice
bob.sendMessage("Alice", "I'm good, thanks!");
// 尝试发送消息给一个未注册的用户
alice.sendMessage("Charlie", "Hey Charlie, are you there?");
}
}
输出结果:
java
Alice sends a message to Bob: Hi Bob, how are you?
Bob sends a message to Alice: I'm good, thanks!
Receiver Charlie is not online.
在这个正例中,User
类不直接持有对其他User
对象的引用,而是通过ChatMediator
中介者来发送消息,ChatMediator
维护了一个用户列表,并负责将消息从发送者传递给接收者,这样,User
类之间的耦合度降低了,因为用户不需要知道如何与其他用户直接通信,他们只需要与中介者交互。此外,如果未来需要改变通信方式或添加额外的通信逻辑,只需要修改ChatMediator
类即可,而不影响User
类。
核心总结
中介者模式总结
通过引入中介者,使得各个组件之间不再直接相互依赖,减少了系统的复杂性,他将原本分散的交互逻辑集中管理,使得这些逻辑更加清晰和易于维护,由于组件间的通信都通过中介者进行,因此添加新组件或修改现有组件的交互方式变得更加容易。但随着系统的扩展,它可能需要处理越来越多的交互逻辑,导致其代码变得庞大且难以维护,为了实现中介者模式,有时可能需要创建额外的抽象类和接口,这可能会增加系统的复杂性和理解难度。
在确实需要降低组件间耦合度的情况下使用中介者模式,避免过度设计,可以考虑与其他设计模式(如观察者模式)结合使用,以实现更灵活和强大的功能。
和其它模式对比
中介者模式和装饰者模式两者的区别:
中介者模式主要用于降低多个对象之间的耦合度,通过引入一个中介者对象,其它所有相关对象都通过该中介者对象进行通信,而不是直接相互引用,当中介者模式中的某一个对象发生改变时,只需要通知中介者对象,由中介者对象负责与其他对象的交互,这样可以简化对象之间的交互,降低系统的复杂性。
装饰者模式则侧重于在不改变对象自身的基础上,动态地给对象添加新的功能或方法,装饰者模式通过创建一个装饰类,将原始类作为成员变量进行包装,并在装饰类中提供与原始类相同的方法,这些方法可以在调用原始类方法之前或之后执行一些额外的操作,这样可以实现对原始类功能的动态扩展,而无需修改原始类的代码。
总结,中介者模式主要用于解决对象之间的紧耦合问题,通过引入中介者来协调对象之间的交互;而装饰者模式则主要用于在不改变原始类的基础上,动态地给对象添加新的功能或方法。