中介者模式


定义

中介者?其实生活中大家再熟悉不过了这个词,我们熟悉的黄牛、房产中介等就是充当中介的角色,将我们的买票、购房等的需求自身消化再代为办理。又比如说中间件,马老师很忙,不能来一个人有事就直接找马老师对吧,所以要找一个中介,客户来了直接找中间人,中间人再和马老师沟通,这样马老师和客户那边就是一个不可见的关系,由中介者角色进行中间协调,马老师也能抽出更多时间去忙别的事了,解放了相当的生产力。

中介者模式(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("买家发布需求...");

结果输出:

买家接收到的消息是:卖家发布需求...
卖家接收到的消息是:买家发布需求...

中介者模式的引入,其实就是为了解决系统对象相互依赖调用的情况,可以想象一下,使用中介者模式后,原本的错综复杂的网络结构就会变成以中介者为中心的网状结构,这是中介者模式要解决的问题。

总结

本节我们介绍了中介者模式,要注意的就是,中介者角色承担了太多的业务功能,并且中介者角色依赖具体的同事角色,一旦同事角色有变更或者添加,中介者角色就需要相应地发生变化,导致二次开发维护变得困难,所以使用的过程中还是要多加注意。


Author: Re:0
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Re:0 !
 Previous
状态模式 状态模式
定义状态模式(Allow an object to alter its behavior when its internal state changes.The object will appear to change its class.
2022-03-12
Next 
观察者模式 观察者模式
定义观察者模式(Observer Pattern)也称发布订阅模式。
2022-03-12
  TOC