简易理解设计模式之:中介者模式——多人聊天室例子
介绍:
中介者模式属于行为型模式。它的定义为:用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互调用,从而使其耦合松散,而且可以独立地改变他们之间的交互。
类图:
Mediator(抽象中介者角色):定义一个接口用于各同事之间的通讯。
ConcreteMediator(具体中介者角色):它从具体的同事对象接受信息,向具体同事对象发出命令,负责协调同事之间的交互。
Colleague(抽象同事角色):通过中介者对象与其它同事类进行交互,并定义所有相互影响的同事类的公共功能。
ConcreteColleagueA/B(具体同事角色):继承于Colleague,每个具体同事类都知道本身在小范围内的行为,而不知道它在大范围内的目的。
用法:
当对象之间的关系复杂且相互依赖时,为防止修改一个对象的行为同时涉及修改很多其它对象的行为,可使用中介者模式。
个人理解:
中介者模式的核心逻辑就是解耦对象‘多对多’的相互依赖关系。当遇到一大堆混乱的对象呈现“网状结构”,利用通过中介者模式解耦对象之间的通讯。理解上就是下图所示:
例子:
日常生活中,我们经常会用社交工具(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哥发送一条消息:好啊好啊~我期待了很久!
安迪收到一条消息:好啊好啊~我期待了很久!
猫猫收到一条消息:好啊好啊~我期待了很久!
-----——分割线---——--
猫猫发送一条消息:我来负责买票!!!
安迪收到一条消息:我来负责买票!!!
Ben哥收到一条消息:我来负责买票!!!
每个用户直接调用sendMessage()的方法就可以完成通讯了,就算是一个100人的大群每个用户也不用改动代码~
总结:
• 中介者模式大大的好处就是降低类的关系复杂度,使对象可以更好地维护和扩展。将多对多的“网状结构”转化成一对多的“星型结构”,复杂的交互逻辑交给了中介者了。
• 这个模式就是迪米特原则的具体体现。复习一下迪米特原则:
迪米特原则(Law Of Demeter,LOD),也称最少知识原则。定义一个对象应该对其他对象有最少的了解。
意思是只与朋友通讯(关联度很高的类)。每个类都会必然用到其它类的属性和方法,这称为耦合。设计类的时候要把功能拆分,尽可能使用一个第三者的朋友来进行两者间的通讯。
• 另外,新手写代码很容易出现一个类文件有上千行代码,N个成员变量放在一起相互调用。所以也不用急于使用中介者模式优化代码,需要考虑整个设计上是不是存在不合理的地方。
感谢您的阅读~
推荐阅读
基础篇:
设计模式前篇之——UML类图必会知识点
设计模式前篇之——一起过一下面向对象的概念
创建型模式:
简易理解设计模式之:简单工厂模式——来试试接入支付功能
简易理解设计模式之:工厂方法模式——数据存储例子
简易理解设计模式之:抽象工厂模式——更换数据库例子
简易理解设计模式之:建造者模式——学习使用“链式调用”
简易理解设计模式之:原型模式——深、浅拷贝的概念
简易理解设计模式之:单例模式——单例模式的几种常用写法
结构型模式:
简易理解设计模式之:适配器模式——Android列表视图控件设计方式
简易理解设计模式之:桥接模式——穿衣服经典案例2
简易理解设计模式之:组合模式——实现View中的树状结构
简易理解设计模式之:装饰模式——穿衣服经典案例
简易理解设计模式之:外观模式——第三方SDK的帮助类
简易理解设计模式之:享元模式——五子棋游戏例子
简易理解设计模式之:代理模式——iOS视图控件设计方式
行为型模式:
简易理解设计模式之:策略模式——优化一下支付功能
简易理解设计模式之:模板方法模式——Android中的BaseActivity基类
简易理解设计模式之:观察者模式——监听与回调
简易理解设计模式之:状态模式——优化登录操作
简易理解设计模式之:备忘录模式——Word文档的工作原理
简易理解设计模式之:迭代器模式——遍历对象的好帮手
简易理解设计模式之:命令模式——实现命令的参数化配置
简易理解设计模式之:责任链模式——OA中请假流程示例
简易理解设计模式之:中介者模式——多人聊天室例子
简易理解设计模式之:解释器模式——语言和文法
简易理解设计模式之:访问者模式——员工考核例子