什么是中介者设计模式?
中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。
中介者模式属于行为型模式。中介者在前端项目中有很广泛的应用,如多个组件同时监听同一个状态,一旦A组件修改了这个状态,需要主动通知其他若干个组件去重新渲染。Redux 是一个状态管理器,如上场景就可以把状态托管给 Redux,所有相关的组件去监听 Redux 的事件,如果状态变化了,则重新渲染。有组件需要去更新状态,则通过 Redux API dispatch 方法,把新的值传给 Redux 的 store。在这里我们能够看出,其实 Redux 扮演了中介者的角色,各个组件之间无需直接通讯,而是只面向 Redux,进而降低系统复杂度和组件间的耦合。
优缺点
优点:
1.降低了类的复杂度,将一对多转化成了一对一。
2.各个类之间的解耦。
3.符合迪米特原则。
缺点:
1.中介者会庞大,变得复杂难以维护。
示例
类似前端的状态管理组件,后台常见的应用如消息队列,我们实现一个简单版本:
public class Component {
private String name;
private String msgGroup;
private Mediator mediator;
public Component(String name, String msgGroup, Mediator mediator) {
this.name = name;
this.msgGroup = msgGroup;
this.mediator = mediator;
new Thread(() -> listen()).start();
}
public void dispatch(String msg) {
this.mediator.dispatch(this.msgGroup, msg);
}
private void listen() {
while(true) {
if (mediator != null) {
final String msg = mediator.consume(this.msgGroup, this.name);
if (msg != null) {
System.out.println(
String.format("[%s] received a msg from %s group: %s", this.name, this.msgGroup, msg));
}
}
}
}
}
static class Mediator {
// 用于存储消息
private volatile Map<String, List<String>> store = new ConcurrentHashMap<>();
// 用于记录每个客户消费消息的index,避免重复消费
private volatile Map<String, Map<String, Long>> consumerIdx = new HashMap<>();
public void dispatch(String msgGroup, String message) {
synchronized (this.getClass()) {
if (!this.store.containsKey(msgGroup)) {
this.store.put(msgGroup, new Vector<>());
}
store.get(msgGroup).add(message);
}
}
public String consume(String msgGroup, String consumerName) {
final List<String> msgQueue = store.get(msgGroup);
synchronized (this.getClass()) {
initIfNotExists(msgGroup, consumerName);
final Long idx = consumerIdx.get(msgGroup).get(consumerName);
if (msgQueue != null && msgQueue.size() > idx) {
final String s = msgQueue.get((int) idx.longValue());
this.consumerIdx.get(msgGroup).put(consumerName, idx + 1);
return s;
}
return null;
}
}
private void initIfNotExists(String msgGroup, String consumerName) {
if (!this.consumerIdx.containsKey(msgGroup)) {
final Map<String, Long> map = new HashMap<>();
this.consumerIdx.put(msgGroup, map);
}
if (!this.consumerIdx.get(msgGroup).containsKey(consumerName)) {
this.consumerIdx.get(msgGroup).put(consumerName, 0L);
}
}
}
// test
public static void main(String[] args) {
final Mediator mediator = new Mediator();
final String msgGroup = "MSG - 01";
final Component componentA = new Component("A", msgGroup, mediator);
final Component componentB = new Component("B", msgGroup, mediator);
mediator.dispatch(msgGroup, "Hello world!");
componentA.dispatch("Hello, This is A, nice to meet u");
componentB.dispatch("This is B, nice to meet u too");
}
Output
[A] received a msg from MSG - 01 group: Hello world!
[B] received a msg from MSG - 01 group: Hello world!
[B] received a msg from MSG - 01 group: Hello, This is A, nice to meet u
[A] received a msg from MSG - 01 group: Hello, This is A, nice to meet u
[B] received a msg from MSG - 01 group: This is B, nice to meet u too
[A] received a msg from MSG - 01 group: This is B, nice to meet u too