关注「Java视界」公众号,获取更多技术干货

中介者模式(作用,原理、怎么用、优缺点)

目录

一、为什么要用中介者模式

二、中介者模式中的角色

三、中介者模式怎么用?

四、中介者模式的优缺点

       优点

       缺点


一、为什么要用中介者模式

中介者模式核心在于中介者这个角色,理解上可以参考现实中的中介者,中介就跟中间人一样,跟桥梁一样。比方说你到了个陌生的城市,要找工作,要找房子。如果一个人冒冒失失的盲目的找,不仅花费的时间跟精力非常大,即使找到了也不是理想中的。这时候中介就发挥作用了。它会根据你的要求,帮你安排那样的工作适合你,跟用人方取得联系。

代码的世界里,如果各个类之间互相依赖,每个类内部引入其他类,当类增多时就会形成网状依赖关系(下图左),这时代码的耦合度就很高;中介者模式可以很好的解耦这种依赖关系,所有类都只和中介者有关联,形成一种星状结构(下图右),通过中介者建立联系,而彼此不需要知道对方是谁,彼此独立,耦合性很低。

                             

说道这你肯定想起了Spring, Spring的一个主要功能就是IOC,各层间、层内不同对象也是不需要事先注入绑定,而是将创建bean的事情全交给Spring处理,Spring负责各方的联系。

中介者模式是迪米特原则的经典体现:迪米特法则(Law of Demeter)又叫作最少知识原则(Least Knowledge Principle 简写LKP),它要求一个对象应该对其他对象保持最少的了解。如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中的一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。 

二、中介者模式中的角色

中介者模式涉及到的角色有四个:

- 抽象中介者角色:抽象中介者角色定义统一的接口,以及一个或者多个事件方法,用于各同事角色之间的通信。

- 具体中介者角色:实现了抽象中介者所声明的事件方法,协调各同事类之间的行为,持有所有同事类对象的引用。

- 抽象同事类角色:定义了抽象同事类,持有抽象中介者对象的引用。

- 具体同事类角色:继承抽象同事类,实现自己业务,通过中介者跟其他同事类进行通信。

三、中介者模式怎么用?

我们实现下面的一个实例:

比如模拟李云龙打仗。李云龙现在要去打鬼子的伏击抢点弹药回来,手底下有3个营,鬼子装备精良,这三个营之间只有互相配合才有胜算。那李云龙就是指挥官(中介者),三个营(同事类)完成各自任务,相互间通信配合都通过李云龙。

抽象中介者:

public interface Mediator {
    // 各营在这里注册,接收各营发来的战况电报
    void receive(String name, Colleague colleague);

    // 下达命令
    void order(String name);
}

 抽象同事类:

public interface Colleague {
    void battle();
    void teamWork();
}

具体同事类:一营

/**
 * Feng, Ge 2020/3/10 0010 15:02
 */
public class FirstCamp implements Colleague {

    private Mediator mediator;

    public FirstCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("一营", this);
    }

    @Override
    public void battle() {
        System.out.println("一营要正面进攻了!");
    }

    @Override
    public void teamWork() {
        System.out.println("报告营长,一营任务正面扛不住了,请求李团长派三营接应!");
        mediator.order("三营");
    }
}

具体同事类:二营

/**
 * Feng, Ge 2020/3/10 0010 15:02
 */
public class SecondCamp implements Colleague {

    private Mediator mediator;

    public SecondCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("二营", this);
    }

    @Override
    public void battle() {
        System.out.println("二营要侧面进攻了!");
    }

    @Override
    public void teamWork() {
        System.out.println("报告营长,二营侧面进攻有些压力,需要一营正面加强火力掩护!");
        mediator.order("一营");
    }
}

具体同事类:三营

/**
 * Feng, Ge 2020/3/10 0010 15:03
 */
public class ThirdCamp implements Colleague {

    private Mediator mediator;

    public ThirdCamp(Mediator mediator) {
        this.mediator = mediator;
        mediator.receive("三营", this);
    }

    @Override
    public void battle() {
        System.out.println("三营在外围接应!");
    }

    @Override
    public void teamWork() {
        System.out.println("报告营长,三营任务已完成,请指示!");
    }
}

具体中介者: 李云龙

/**
 * Feng, Ge 2020/3/10 0010 14:51
 */
public class YunLongLi implements Mediator {

    private Map<String,Colleague> map = new HashMap<String , Colleague>();

    @Override
    public void receive(String name, Colleague colleague) {
        map.put(name, colleague);
    }

    @Override
    public void order(String name) {
        map.get(name).battle();
    }
}

测试类:

/**
 * Feng, Ge 2020/3/10 0010 15:49
 */
public class MdiatorTest {
    public static void main(String[] args) {
        Mediator mediator = new YunLongLi();
        FirstCamp firstCamp = new FirstCamp(mediator);
        SecondCamp secondCamp = new SecondCamp(mediator);
        ThirdCamp thirdCamp = new ThirdCamp(mediator);

        firstCamp.battle();
        firstCamp.teamWork();
        System.out.println("====================================");
        secondCamp.battle();
        secondCamp.teamWork();
        System.out.println("====================================");
        thirdCamp.battle();
        thirdCamp.teamWork();
        System.out.println("把老子的意大利炮来出来,轰他娘的小鬼子,秀琴对不住了,开炮!!!!!");
    }
}

结果:

一营要正面进攻了!
报告营长,一营任务正面扛不住了,请求李团长派三营接应!
三营在外围接应!
====================================
二营要侧面进攻了!
报告营长,二营侧面进攻有些压力,需要一营正面加强火力掩护!
一营要正面进攻了!
====================================
三营在外围接应!
报告营长,三营任务已完成,请指示!
把老子的意大利炮来出来,轰他娘的小鬼子,秀琴对不住了,开炮!!!!!

以上,各营的行动彼此需要支援的时候,例如一营需要三营外围接应的时候,不是一营长和三营长直接对话,而是通过李云龙,李云龙根据name去调用具体的map.get(name).battle()方法。

四、中介者模式的优缺点

优点

1)解耦。把同事类原来一对多的依赖变成一对一的依赖,降低同事类的耦合度,同时也符合了迪米特原则。

缺点

1)中介者模式把业务流程和协调都写在中介者,当同事类越多,中介者的业务就越复杂,造成不好管理的弊端。

五、使用场景

中介者模式很容易实现呢,但是也容易误用,不要着急使用,先要思考你的设计是否合理。
当对象之间的交互变多时,为了防止一个类会涉及修改其他类的行为,可以使用中介者模式,将系统从网状结构变为以中介者为中心的星型结构。

中介者模式和代理模式的区别:

代理模式是结构型设计模式,它有很多种类型,主要是在访问对象时引入一定程度的间接性,由于有间接性,就可以附加多种的用途,比如进行权限控制。中介者模式则是为了减少对象之间的相互耦合。

外观模式和中介者模式:
外观模式主要是以封装和隔离为主要任务,中介者则是调停同事类之间的关系,因此,中介者具有部分业务的逻辑控制。他们之间的主要区别为:

  • 外观模式的子系统如果脱离外观模式还是可以运行的,而中介者模式增加了业务逻辑,同事类不能脱离中介者而独自存在。
  • 外观模式中,子系统是不知道外观类的存在的,而中介者模式中,每个同事类都知道中介者。
  • 外观模式将子系统的逻辑隐藏,用户不知道子系统的存在,而中介者模式中,用户知道同事类的存在。
posted @ 2022-06-25 14:02  沙滩de流沙  阅读(959)  评论(0编辑  收藏  举报

关注「Java视界」公众号,获取更多技术干货