介绍:

中介者模式属于行为型模式。它的定义为:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互调用,从而使其耦合松散,而且可以独立地改变他们之间的交互。

类图:

简易理解设计模式之:中介者模式——多人聊天室例子_中介者


Mediator(抽象中介者角色):定义一个接口用于各同事之间的通讯。

ConcreteMediator(具体中介者角色):它从具体的同事对象接受信息,向具体同事对象发出命令,负责协调同事之间的交互。

Colleague(抽象同事角色):通过中介者对象与其它同事类进行交互,并定义所有相互影响的同事类的公共功能。

ConcreteColleagueA/B(具体同事角色):继承于Colleague,每个具体同事类都知道本身在小范围内的行为,而不知道它在大范围内的目的。

用法:
当对象之间的关系复杂且相互依赖时,为防止修改一个对象的行为同时涉及修改很多其它对象的行为,可使用中介者模式。

个人理解:
中介者模式的核心逻辑就是解耦对象‘多对多’的相互依赖关系。当遇到一大堆混乱的对象呈现“网状结构”,利用通过中介者模式解耦对象之间的通讯。理解上就是下图所示:

简易理解设计模式之:中介者模式——多人聊天室例子_中介者模式_02


例子:

日常生活中,我们经常会用社交工具(QQ、微信)进行聊天。在这其中,群组聊天的设计正是中介者模式的例子,我们下面模拟一下:

设计思路:每个聊天用户就相当于同事类,聊天服务器就相当于我们的中介者。整个流程是用户向聊天服务器发送一条消息,服务器会将此消息发送给群组中的所有人。

设计多人聊天群组
1、创建抽象中介者角色

public abstract class ChatMediator {
public abstract void register(ChatClient client);
public abstract void notice(ChatClient client,String message);
}

定义一些接口用于同事类的通讯。在这里我们定义一个加入群聊的行为和向所有人发送通知的行为。

2、实现具体中介者角色

public class ChatServer extends ChatMediator {

private List<ChatClient> clientList = new ArrayList<>();

@Override
public void notice(ChatClient client, String message) {
for (ChatClient c : clientList) {
if (!client.equals(c)) {
c.receiveMessage(message);
}
}
}

@Override
public void register(ChatClient client) {
if (client != null && !clientList.contains(client)) {
clientList.add(client);
}
}

}

具体中介者负责协调同事类之间的交互,notice()方法向所群组中除了自己之外的用户发送消息。

3、创建抽象同事类

public abstract class ChatClient {
protected ChatMediator mediator;

public ChatClient(ChatMediator mediator){
this.mediator = mediator;
}

public abstract void sendMessage(String message);
public abstract void receiveMessage(String message);
}

每个用户都有一个发送消息的方法和接收消息的方法,而消息的传递则通过中介者对象mediator处理。

4、实现具体同事类

public class Andy extends ChatClient {

public Andy(ChatMediator mediator) {
super(mediator);
mediator.register(this);
}

@Override
public void sendMessage(String message) {
System.out.println();
System.out.println("安迪发送一条消息:" + message);
mediator.notice(this, message);
}

@Override
public void receiveMessage(String message) {
System.out.println("安迪收到一条消息:" + message);
}
}

具体同事类忽略Ben、Cat、David等等的用户,实现相似!

对于每个具体同事类(用户)而言,它并不需要知道这个群里面到底有多少人,只知道自己是负责发送和接收消息的。

5、测试与运行结果

public class Group {

public static void main(String[] args) {
//聊天服务器
ChatServer chatServer = new ChatServer();

//三个小伙伴
Andy andy = new Andy(chatServer);
Ben ben = new Ben(chatServer);
Cat cat = new Cat(chatServer);

System.out.println("=====群聊信息=====");
andy.sendMessage("今晚去看复仇者联盟4吧!");
System.out.println("-----——分割线——-----");
ben.sendMessage("好啊好啊~我期待了很久!");
System.out.println("-----——分割线---——--");
cat.sendMessage("我来负责买票!!!");
}
}
=====群聊信息=====

安迪发送一条消息:今晚去看复仇者联盟4吧!
Ben哥收到一条消息:今晚去看复仇者联盟4吧!
猫猫收到一条消息:今晚去看复仇者联盟4吧!
-----——分割线——-----
Ben哥发送一条消息:好啊好啊~我期待了很久!
安迪收到一条消息:好啊好啊~我期待了很久!
猫猫收到一条消息:好啊好啊~我期待了很久!
-----——分割线---——--

每个用户直接调用sendMessage()的方法就可以完成通讯了,就算是一个100人的大群每个用户也不用改动代码~

总结:
• 中介者模式大大的好处就是降低类的关系复杂度,使对象可以更好地维护和扩展。将多对多的“网状结构”转化成一对多的“星型结构”,复杂的交互逻辑交给了中介者了。

• 这个模式就是迪米特原则的具体体现。复习一下迪米特原则:

迪米特原则(Law Of Demeter,LOD),也称最少知识原则。定义一个对象应该对其他对象有最少的了解。

意思是只与朋友通讯(关联度很高的类)。每个类都会必然用到其它类的属性和方法,这称为耦合。设计类的时候要把功能拆分,尽可能使用一个第三者的朋友来进行两者间的通讯。

• 另外,新手写代码很容易出现一个类文件有上千行代码,N个成员变量放在一起相互调用。所以也不用急于使用中介者模式优化代码,需要考虑整个设计上是不是存在不合理的地方。

感谢您的阅读~