中介者模式
简介
中介者模式要解决的就是复杂功能应用之间的重复调用
,在这中间添加一层中介者包装服务
,对外提供简单、通用、易扩展的服务能力。
这样的设计模式几乎在我们日常生活和实际业务开发中都会见到,例如;飞机🛬降落有小姐姐在塔台喊话、无论哪个方向来的候车都从站台上下、公司的系统中有一个中台专门为你包装所有接口和提供统一的服务等等,这些都运用了中介者模式。除此之外,你用到的一些中间件,他们包装了底层多种数据库的差异化,提供非常简单的方式进行使用。
例如下面这个结构,如果每个元素两两之间要产生联系,关系就会变得错综复杂。
但是加了中介者之后,相互之间就可以解耦了。变成如下的关系结构。
角色结构
抽象中介者(Mediator)角色
:抽象中介者角色定义统一的接口,用于各同事角色之间的通信。例子中君主类代表的就是这个角色。
具体中介者(ConcreteMediator)角色
:具体中介者角色通过协调各同事角色,实现协作行为,为此它要指导并引用各个同事角色。例子中皇上代表的就是这个角色。
同事(Colleague)角色
:每一个同事角色都知道对应的具体中介者角色,而且与其他的同事角色通信的时候,一定要通过中介者角色协作。例子中老纪跟和二就是代表的这个角色。
代码实现
举例
和二跟老纪都是朝廷大臣,但是互相看不顺眼,在皇上面前和和气气,背地里各自互相参对方。当然有时候皇上颁布旨意时让两个大臣一起合作去完成任务,他们也会相互合作的。和二跟老纪都想收拾对方,但是奈何双方官职不相上下,所以当想收拾对方时就会通过皇上来实现,这个时候我们就当皇上理解为中介者。下面用代码来实现这个过程。
项目结构
代码
官员抽象类
/**
* 官员(大臣)抽象类
*/
public abstract class Official {
protected Monarch monarch;
/**
* 每个官员必然要与君主有联系
* @param monarch
*/
public Official(Monarch monarch){
this.monarch = monarch;
}
/**
* 在抽象官员类中添加与中介者取得联系的方法
* @param monarch
*/
public void setMonarch(Monarch monarch){
this.monarch = monarch;
}
}
君主抽象类
/**
* 君主抽象类
*/
public abstract class Monarch {
/**
* 君主保持着和各个官员的联系
*/
protected ConcurrentHashMap<String,Official> officials = new ConcurrentHashMap<>();
/**
* 录用官员
* @param name
* @param official
*/
public void addOfficial(String name,Official official){
this.officials.put(name,official);
}
/**
* 将官员革职查办
* @param name
*/
public void removeOfficial(String name){
this.officials.remove(name);
}
/**
* 处理各个官员之间的互相参奏的折子
* @param name
* @param method
*/
public abstract void execute(String name,String method);
}
老纪
/**
* 老纪
*/
public class LaoJi extends Official{
/**
* 每个官员必然要与君主有联系
*
* @param monarch
*/
public LaoJi(Monarch monarch) {
super(monarch);
}
/**
* 做好本职工作
*/
public void self(){
System.out.println("启奏皇上,臣老纪参与编写的四库全书已经完成。");
}
/**
* 参其他官员或与其他官员合作
*/
public void out(){
System.out.println("启奏皇上,臣老纪要参和二一本,秀女选拔工作到现在还没完成,理应当革职查办。");
super.monarch.execute("heEr","self");
}
}
和二
/**
* 和二
*/
public class HeEr extends Official {
/**
* 每个官员必然要与君主有联系
*
* @param monarch
*/
public HeEr(Monarch monarch) {
super(monarch);
}
/**
* 做好本职工作
*/
public void self(){
System.out.println("启奏皇上,臣和二掌管的秀女选拔工作已经完成。");
}
/**
* 参其他官员或与其他官员合作
*/
public void out(){
System.out.println("启奏皇上,臣和二要参老纪一本,四库全书到目前还没编写完成,理应问斩。");
super.monarch.execute("laoji","self");
}
}
黄三(乾隆皇上)
/**
* 黄三(皇上)
*/
public class HuangSan extends Monarch {
/**
* 处理各个官员之间的互相参奏的折子
*
* @param name
* @param method
*/
@Override
public void execute(String name, String method) {
//做好自己份内的事情
if("self".equals(method)){
if("laoji".equals(name)){
((LaoJi)super.officials.get(name)).self();
}else {
((HeEr)super.officials.get(name)).self();
}
//我要参别人一本
}else {
if("laoji".equals(name)){
((LaoJi)super.officials.get(name)).out();
}else {
((LaoJi)super.officials.get(name)).out();
}
}
}
}
测试类
public class ApiTest {
@Test
public void testCommand(){
//创建一个君主
Monarch monarch = new HuangSan();
//创建两个官员
LaoJi laoJi = new LaoJi(monarch);
HeEr heEr = new HeEr(monarch);
//君主和两个官员建立关系
monarch.addOfficial("laoji",laoJi);
monarch.addOfficial("heEr",heEr);
//有本奏上,无本退朝。
//laoJi.self();
laoJi.out();
System.out.println("---------------启奏完毕");
//heEr.self();
heEr.out();
System.out.println("---------------启奏完毕");
}
}
总结
优点
中介者模式简化了对象之间的交互
,它用中介者和同事的一对多交互代替了原来同事之间的多对多交互,一对多关系更容易理解、维护扩展,将原本难以理解的网状结构转换成相对简单的星型结构。中介者模式可将各同事对象解耦
。中介者有利于各同事之间的松耦合,我们可以独立的改变和复用每一个同事和中介者,增加新的中介者和新的同事类都比较方便,更好的符合“开闭原则”。可以减少子类生成
,中介者将原本分布于多个对象间的行为集中在一起,改变这些行为只需生成新的中介者子类即可,这使得各个同事类可被重用,无须对同事类进行扩展。
缺点
在具体中介者类中包含了大量同事之间的交互细节,可能会导致具体中介者类非常复杂,使得系统难以维护。
适用场景
- 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。