(二十二)、设计模式 之 中介者模式(mediator)
(二十二)、设计模式 之 中介者模式(mediator)
1、简介
定义:用一个中介对象来封装一系列的对象交互。中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。
简单来说,使得对象间多对多的关系, 变成一对一的关系。
中介模式解决问题的思路
中介者模式的解决思路很简单,中介者模式通过引入一个中介对象,让其他的对象都只和中介对象交互,而中介对象知道如何和其他所有的对象交互,这样对象之间的交互关系就没有了,从而实现了对象之间的解耦对于中介对象而言,所有相互交互的对象,被视为同事类,中介对象就是来维护各个同事之间的关系,而所有的同事类都只是和中介对象交互。每个同事对象,当自己发生变化的时候,不需要知道这会引起其他对象有什么变化它只需要通知中介者就可以了,然后由中介者去与其他对象交互。这样松散耦合带来的好处是,除了让同事对象之间相互没有关联外,还有利于功能的修改和扩展。有了中介者以后,所有的交互都封装到中介者对象里面,各个对象就不再需要维护这些关系了。扩展关系的时候也只需要扩展或修改中介者对象就可以了。
场景问题
如果电脑里面没有了主板,那么各个配件之间就必须自行相互交互,以互相传送数据。理论上说,基本上各个配件相互之间都存在交互数据的可能,如图:
所幸是有了主板,各个配件的交互完全通过主板来完成,每个配件都只需要和主板交互,而主板知道如何和所有的配件打交道,那就简单多了,有主板后的结构如图所示:
中介者模式可以使对象之间的关系数量急剧减少,通过引入中介者对象,可以将系统的网状结构变成以中介者为中心的星形结构 ,从上右图中可以看到,任何一个类的变动,只会影响的类本身,以及中介者,这样就减小了系统的耦合。一个好的设计,必定不会把所有的对象关系处理逻辑封装在本类中,而是使用一个专门的类来管理那些不属于自己的行为。
如果在一个系统中对象之间存在多对多的相互关系,我们可以将对象之间的一些交互行为的细节从各个对象中分离出来,并集中封装在一个中介者对象中,并由该中介者进行统一协调,这样对象之间多对多的复杂关系就转化为相对简单的一对多关系。通过引入中介者来简化对象之间的复杂交互,中介者模式是“迪米特法则”的一个典型应用。
2、中介者模式结构说明
- 抽象中介者接口(AbstractMediator): 在里面定义各个同事之间交互需要的方法,可以是公共的通信方法,也可以是小范围的交互方法。
- 具体中介者实现对象(ConcreteMediator): 它需要了解并维护各个同事对象,并负责具体的协调各同事对象的交互关系。
- 同事类的定义(Colleague): 通常实现成为抽象类,主要负责约束同事对象的类型并实现一些具体同事类之间的公共功能,比如,每个具体同事类都应该知道中介者对象,也就是具体同事类都会持有中介者对象,都可以定义到这个类里面。
- 具体的同事类(ConcreteColleague): 实现自己的业务,在需要与其他同事通信的时候,就与持有的中介者通信,中介者会负责与其他的同事交互。
3、中介者模式的代码实现
/**
* @Author
* @ClassName Mediator
* @Description 抽象中介者
* @Date 2023/12/19 23:36
* @Version 1.0
*/
public abstract class AbstractMediator {
/**
* 申明一个联络方法, 参数可以自定义
* @param msg 消息
* @param abstractPerson 具体的同事类
*/
public abstract void send(String msg, AbstractPerson abstractPerson);
}
/**
* @Author
* @ClassName ConcreteMediator
* @Description 具体的中介机构-中介机构拥有所有的有交互关系的同事对象
* @Date 2023/12/19 23:45
* @Version 1.0
*/
@Data
public class ConcreteMediator extends AbstractMediator{
/**
* 房主
*/
private HouseOwner houseOwner;
/**
* 租房者
*/
private Tenant tenant;
@Override
public void send(String msg, AbstractPerson person) {
if (person == houseOwner) {
// 如果是房主,则租房者获得信息
tenant.getMessage(msg);
} else {
// 反正则是房主获得信息
houseOwner.getMessage(msg);
}
}
}
/**
* @Author
* @ClassName Person
* @Description 抽象同事类
* @Date 2023/12/19 23:37
* @Version 1.0
*/
public abstract class AbstractPerson {
protected String name;
/**
* 持有一个中介对象,可以和中介对象交互
*/
protected AbstractMediator abstractMediator;
public AbstractPerson(String name, AbstractMediator abstractMediator){
this.name = name;
this.abstractMediator = abstractMediator;
}
}
/**
* @Author
* @ClassName HouseOwner
* @Description 具体同事类-房屋拥有者
* @Date 2023/12/19 23:39
* @Version 1.0
*/
public class HouseOwner extends AbstractPerson {
public HouseOwner(String name, AbstractMediator abstractMediator) {
super(name, abstractMediator);
}
/**
* 与中介者联系
*
* @param message
*/
public void send(String message) {
abstractMediator.send(message, this);
}
/**
* 获取信息
* @param message
*/
public void getMessage(String message){
System.out.println("房主" + name +"获取到的信息:" + message);
}
}
/**
* @Author
* @ClassName Tenant
* @Description 具体同事类-租户
* @Date 2023/12/19 23:43
* @Version 1.0
*/
public class Tenant extends AbstractPerson {
public Tenant(String name, AbstractMediator abstractMediator) {
super(name, abstractMediator);
}
/**
* 与中介者联系
* @param message 交互信息
*/
public void send(String message){
abstractMediator.send(message, this);
}
/**
* 获取信息
* @param message
*/
public void getMessage(String message){
System.out.println("租房者" + name +"获取到的信息:" + message);
}
}
/**
* @Author
* @ClassName ClientTest
* @Description 客户端测试
* @Date 2023/12/19 23:53
* @Version 1.0
*/
public class ClientTest {
public static void main(String[] args) {
// 一个房主、一个租房者、一个中介机构
ConcreteMediator mediator = new ConcreteMediator();
// 房主和租房者只需要知道中介机构即可
HouseOwner houseOwner = new HouseOwner("张三", mediator);
Tenant tenant = new Tenant("李四", mediator);
//中介结构要知道房主和租房者
mediator.setHouseOwner(houseOwner);
mediator.setTenant(tenant);
tenant.send("需要租三室的房子");
houseOwner.send("我这有三室的房子,你需要租吗?");
}
}
4、中介者模式的优缺点
优点
松散耦合:中介者模式通过把多个同事对象之间的交互封装到中介者对象里面,从而使得同事对象之间松散耦合,基本上可以做到互补依赖。这样一来,同事对象就可以独立地变化和复用,而不再像以前那样“牵一处而动全身”了。
集中控制交互:多个同事对象的交互,被封装在中介者对象里面集中管理,使得这些交互行为发生变化的时候,只需要修改中介者对象就可以了,当然如果是已经做好的系统,那么就扩展中介者对象,而各个同事类不需要做修改。
一对多关联转变为一对一的关联: 没有使用中介者模式的时候,同事对象之间的关系通常是一对多的,引入中介者对象以后,中介者对象和同事对象的关系通常变成双向的一对一,这会让对象的关系更容易理解和实现。
缺点
当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
5、使用场景
- 系统中对象之间存在复杂的引用关系,系统结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。可以通过引入中介者类来实现,在中介者中定义对象交互的公共行为,如果需要改变行为则可以增加新的具体中介者类。