中介者模式通过引入中介类降低对象间耦合度,在电商平台中,卖家、买家、物流公司和支付平台原本需复杂交互,在引入“交易中介”类后,各角色只需与中介交互,由中介协调各方操作,从而简化了交互流程,降低了类间依赖,使系统更灵活可维护。
定义
中介者模式主要用于减少类之间的耦合,它用一个中介类来封装一系列对象间的交互,使这些对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
举一个业务中的例子来说明,假设有一个电商平台,其中有卖家、买家、物流公司和支付平台四个角色,在没有中介者的情况下,这四个角色之间可能需要进行复杂的交互,比如卖家要直接联系物流公司发货,买家要直接联系支付平台进行支付等,这样的设计会导致类之间的耦合度很高,一旦某个角色发生变化,可能会影响到其他角色。
而引入中介者模式后,可以设计一个电商平台的“交易中介”类,这个类中介了卖家、买家、物流公司和支付平台之间的所有交互,卖家只需要将商品信息和买家信息提交给交易中介,交易中介会负责联系物流公司进行发货,并通知买家进行支付,买家支付完成后,交易中介会通知卖家和物流公司更新订单状态,这样,卖家、买家、物流公司和支付平台之间的耦合度就大大降低了,每个角色只需要和交易中介进行交互,而不需要直接和其他角色进行交互。
在这个场景中中,交易中介类就起到了中介者的作用,它将一系列对象间的交互封装起来,使这些对象之间的耦合度降低,提高了系统的灵活性和可维护性。
代码案例
反例
下面是一个未使用中介者模式的反例代码,假如,有一个聊天应用的简单模型,其中包括User
(用户)和GroupChat
(群聊)类,每个User
对象都直接与其他User
对象通信,如下代码演示:
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."); }
}
输出结果,如下:
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
类作为中介者,封装了用户之间的通信逻辑,使得用户之间不需要直接相互引用,如下代码:
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?"); }
}
输出结果:
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
类。
核心总结
中介者模式总结
通过引入中介者,使得各个组件之间不再直接相互依赖,减少了系统的复杂性,他将原本分散的交互逻辑集中管理,使得这些逻辑更加清晰和易于维护,由于组件间的通信都通过中介者进行,因此添加新组件或修改现有组件的交互方式变得更加容易。但随着系统的扩展,它可能需要处理越来越多的交互逻辑,导致其代码变得庞大且难以维护,为了实现中介者模式,有时可能需要创建额外的抽象类和接口,这可能会增加系统的复杂性和理解难度。
在确实需要降低组件间耦合度的情况下使用中介者模式,避免过度设计,可以考虑与其他设计模式(如观察者模式)结合使用,以实现更灵活和强大的功能。
和其它模式对比
中介者模式和装饰者模式两者的区别:
中介者模式主要用于降低多个对象之间的耦合度,通过引入一个中介者对象,其它所有相关对象都通过该中介者对象进行通信,而不是直接相互引用,当中介者模式中的某一个对象发生改变时,只需要通知中介者对象,由中介者对象负责与其他对象的交互,这样可以简化对象之间的交互,降低系统的复杂性。
装饰者模式则侧重于在不改变对象自身的基础上,动态地给对象添加新的功能或方法,装饰者模式通过创建一个装饰类,将原始类作为成员变量进行包装,并在装饰类中提供与原始类相同的方法,这些方法可以在调用原始类方法之前或之后执行一些额外的操作,这样可以实现对原始类功能的动态扩展,而无需修改原始类的代码。
总结,中介者模式主要用于解决对象之间的紧耦合问题,通过引入中介者来协调对象之间的交互;而装饰者模式则主要用于在不改变原始类的基础上,动态地给对象添加新的功能或方法。