定义
中介者?其实生活中大家再熟悉不过了这个词,我们熟悉的黄牛、房产中介等就是充当中介的角色,将我们的买票、购房等的需求自身消化再代为办理。又比如说中间件,马老师很忙,不能来一个人有事就直接找马老师对吧,所以要找一个中介,客户来了直接找中间人,中间人再和马老师沟通,这样马老师和客户那边就是一个不可见的关系,由中介者角色进行中间协调,马老师也能抽出更多时间去忙别的事了,解放了相当的生产力。
中介者模式(Mediator)的定义:定义一个中介对象来封装对象之间的交互,使原有对象之间耦合松散,并且可以独立地改变它们之间的交互。
还记得迪米特法则吗?迪米特法则的初衷在于降低类之间的耦合,中介者模式就是迪米特法则的典型应用。
组成角色
中介者模式的组成角色如下:
- 中介者(又称仲裁者,Mediator):负责定义与 Colleague 角色进行通信和做出角色的接口;
- 具体中介者、仲裁者(ConcreteMediator):负责实现 Mediator 角色定义的接口,负责具体的业务执行;
- 同事角色(Colleague):负责定义与 Mediator 角色进行通信的接口;
- 具体同事角色(ConcreteColleague):实现 Colleague 角色定义的接口,一般会有多个实现类。
类图的话比较简单,就没有细分中介者角色了,抽象成了如下三种角色:
代码实现
每个同事角色都知道中介者角色的存在,比如房屋买卖中,卖家和买家都知道房产中介的存在一样,也就是同事角色间进行通信时都必须依赖于中介者角色,当然,如果同事角色只是简单对自身状态进行变更,不会影响其他同事角色的状态时就不需要中介者角色,这种同事角色自发改变自身行为的行为称为自发行为,第二种行为就是依赖其他对象进行操作的行为。
中介者模式的代码如下:
// 抽象同事类
abstract class Colleague {
// 每个同事类角色都必须知道中介者角色的存在
protected Mediator mediator;
public Colleague(Mediator mediator) {
this.mediator = mediator;
}
}
// 具体同事类
class Colleague1 extends Colleague {
public Colleague1(Mediator mediator) {
super(mediator);
}
// 自发行为
public void doSelfMethod1() {
System.out.println("11111");
}
// 依赖方法
public void depMethod1() {
// 委托给中介者处理的任务
this.mediator.doSomething();
}
}
// 具体同事类
class Colleague2 extends Colleague {
public Colleague2(Mediator mediator) {
super(mediator);
}
// 自发行为
public void doSelfMethod2() {
System.out.println("22222");
}
// 依赖方法
public void depMethod2() {
// 委托给中介者处理的任务
this.mediator.doSomething();
}
}
// 抽象中介者角色
abstract class Mediator {
// 中介者要协调的同事角色
protected Colleague1 c1;
protected Colleague2 c2;
// 中介者模式的业务逻辑抽象
abstract void doSomething();
public Colleague1 getC1() {
return c1;
}
public void setC1(Colleague1 c1) {
this.c1 = c1;
}
public Colleague2 getC2() {
return c2;
}
public void setC2(Colleague2 c2) {
this.c2 = c2;
}
}
// 具体中介者
class ConcreteMediator extends Mediator{
@Override
void doSomething() {
this.c1.doSelfMethod1();
this.c2.doSelfMethod2();
}
}
具体的测试类:
// 声明中介者
Mediator mediator = new ConcreteMediator();
// 定义两个同事角色
Colleague1 c1 = new Colleague1(mediator);
Colleague2 c2 = new Colleague2(mediator);
// 给中介者设置同事角色
mediator.setC1(c1);
mediator.setC2(c2);
c1.depMethod1();
优缺点
中介者模式的优点:
- 弱化对象间的依赖关系,即松耦合,降低同时类的耦合度,符合迪米特法则
- 将对象间的调用关系进行封装,使得对象更容易复用
中介者模式的缺点: - 如果对象增多,就要去修改抽象中介者和具体的中介者角色
- 中介者角色承担了太多了业务逻辑功能,流程复杂时就会显得比较臃肿,不好管理
应用场景
中介者模式的应用场景一般比较明确,当系统有一系列对象需要相互调用,为弱化对象间的依赖关系,使得这些对象之间松耦合。
生活中,最普遍熟悉的例子就是房屋中介或者 qq 群这种聊天案例,这里我们以房屋中介为例,中介公司就好比我们的中介者角色,而业主和买家就构成了两个不同的同事角色,买卖双方之间的这种交互就可以交给中介者去对接协调:
// 抽象的中介公司角色,中介者角色中一般都要包含各个同事角色,因为它要负责这些对象之间的交互
abstract class MeditorCompany {
// 中介公司名称
private String name;
protected ColleagueSeller seller; // 卖家-同事角色
protected ColleagueBuyer buyer; // 买家-同事角色
// 发布一个需求,由中介公司去代为发布,入参为需求内容、发布人
abstract void publish(String message, Colleaguer colleaguer);
public MeditorCompany(String name) {
this.name = name;
}
public ColleagueSeller getSeller() {
return seller;
}
public void setSeller(ColleagueSeller seller) {
this.seller = seller;
}
public ColleagueBuyer getBuyer() {
return buyer;
}
public void setBuyer(ColleagueBuyer buyer) {
this.buyer = buyer;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
// 具体的中介公司-贝克找房
class MeditorCompanyBeiKe extends MeditorCompany{
public MeditorCompanyBeiKe(String name) {
super(name);
}
@Override
void publish(String message, Colleaguer colleaguer) {
if (colleaguer instanceof ColleagueSeller) { // 如果是卖家发布,则买家进行接收
buyer.accept(message);
} else if(colleaguer instanceof ColleagueBuyer) { // 如果是买家发布,则卖家进行接收
seller.accept(message);
}
}
}
// 抽象的同事角色
abstract class Colleaguer {
protected MeditorCompany meditorCompany; // 对同事类而言,中介者必须是可见的
public Colleaguer(MeditorCompany meditorCompany) {
this.meditorCompany = meditorCompany;
}
}
// 卖家-同事角色
class ColleagueSeller extends Colleaguer {
public ColleagueSeller(MeditorCompany meditorCompany) {
super(meditorCompany);
}
// 同事类发布一个需求,不过是通过中介公司去发布,发布人是自己
public void send(String message) {
meditorCompany.publish(message, this);
}
public void accept(String message) {
System.out.println("卖家接收到的消息是:" + message);
}
}
// 买家-同事角色
class ColleagueBuyer extends Colleaguer {
public ColleagueBuyer(MeditorCompany meditorCompany) {
super(meditorCompany);
}
public void send(String message) {
meditorCompany.publish(message, this);
}
public void accept(String message) {
System.out.println("买家接收到的消息是:" + message);
}
}
测试如下:
// 定义一个中介者
MeditorCompany meditorCompany = new MeditorCompanyBeiKe("贝克找房");
// 定义一个卖家一个买家同事类
ColleagueSeller colleagueSeller = new ColleagueSeller(meditorCompany);
ColleagueBuyer colleagueBuyer = new ColleagueBuyer(meditorCompany);
// 给中介公司注册买家、卖家
meditorCompany.setBuyer(colleagueBuyer);
meditorCompany.setSeller(colleagueSeller);
// 操作
colleagueSeller.send("卖家发布需求...");
colleagueBuyer.send("买家发布需求...");
结果输出:
买家接收到的消息是:卖家发布需求...
卖家接收到的消息是:买家发布需求...
中介者模式的引入,其实就是为了解决系统对象相互依赖调用的情况,可以想象一下,使用中介者模式后,原本的错综复杂的网络结构就会变成以中介者为中心的网状结构,这是中介者模式要解决的问题。
总结
本节我们介绍了中介者模式,要注意的就是,中介者角色承担了太多的业务功能,并且中介者角色依赖具体的同事角色,一旦同事角色有变更或者添加,中介者角色就需要相应地发生变化,导致二次开发维护变得困难,所以使用的过程中还是要多加注意。