「设计模式」中介者模式

1,379 阅读3分钟

一、概述

中介者模式(Mediator Pattern)是用来降低多个对象和类之间的通信复杂性。这种模式提供了一个中介类,该类通常处理不同类之间的通信,并支持松耦合,使代码易于维护。

通俗理解,把复杂的网状结构关系分离为星型结构关系。

中介者模式4种角色:

  • 抽象中介者(Mediator)角色:抽象中介者角色定义统一的接口,以及一个或者多个事件方法,用于各同事角色之间的通信。
  • 具体中介者(ConcreteMediator)角色:实现了抽象中介者所声明的事件方法,协调各同事类之间的行为,持有所有同事类对象的引用。
  • 抽象同事(Colleague)角色:定义了抽象同事类,持有抽象中介者对象的引用。
  • 具体同事(ConcreteColleague)角色:继承抽象同事类,实现自己业务,通过中介者跟其他同事类进行通信。

二、优缺点

优点

  • 各个类之间的解耦,方便复用各个组件,降低了类的复杂度,将一对多转化成了一对一。
  • 单一职责原则,可以将多个组件间的交流抽取到同一位置,使其更易于理解和维护。
  • 开闭原则,组件关系包含在中介者中,无需修改组件就能新增中介者,定义新的合作方式。

缺点

  • 中介者会庞大,变得复杂难以维护,一段时间后,中介者可能会演化成为上帝对象。
  • 中介者角色承担了较多的责任,一旦中介者对象出现问题,整个系统将受到重大影响。
  • 新增组件类时,需要修改抽象中介者和具体中介者,可以使用观察者模式和状态模式来优化这个问题。

三、实现方式

模拟一个简单的场景,当我们去了美食城,以前都是想吃啥的去那个店铺面前点菜,现在美食城斥巨资做了一个下单平台(中介者),顾客只需要在这个平台下单,平台会通知对应的店铺。

抽象商铺类

public abstract class Shop {

    protected String name;

    public abstract void action(String foodName);

    public String getName() {
        return name;
    }
}

具体商铺类

public class ShopA extends Shop {

    public ShopA(String name){
        this.name = name;
    }

    @Override
    public void action(String foodName) {
        System.out.println(this.name + "已收到,顾客点了:" + foodName);
    }
}

public class ShopB extends Shop{

    public ShopB(String name){
        this.name = name;
    }

    @Override
    public void action(String foodName) {
        System.out.println(this.name + "已收到,顾客点了:" + foodName);
    }
}

抽象中介类

public abstract class Mediator {

    protected List<Shop> shops = new ArrayList<>();

    public  abstract void add(Shop shop);

    public  abstract void notice(String shopName, String foodName);
}

具体中介类

public class ConcreteMediator extends Mediator{

    @Override
    public void add(Shop shop) {
        shops.add(shop);
    }

    @Override
    public void notice(String shopName, String foodName) {
        for(Shop shop: shops){
            if(shop.getName().equals(shopName)){
                shop.action(foodName);
                return;
            }
        }
        System.out.println(shopName + "未开店");
    }

}

客户端

public class Client {
    public static void main(String[] args) {
        Mediator mediator = new ConcreteMediator();
        //先添加几个店铺
        mediator.add(new ShopA("南城香"));
        mediator.add(new ShopB("老杨羊汤"));

        System.out.println("在南城香点“一碗馄饨”");
        mediator.notice("南城香","一碗馄饨");
        System.out.println("-----------------------------------");

        System.out.println("在老杨羊汤点“一碗羊杂汤”");
        mediator.notice("老杨羊汤","一碗羊杂汤");

        System.out.println("-----------------------------------");
        System.out.println("在绝味鸭脖点“一斤鸭脖”");
        mediator.notice("绝味鸭脖","一斤鸭脖");
    }
}

结果输出

在南城香点“一碗馄饨”
南城香已收到,顾客点了:一碗馄饨
-----------------------------------
在老杨羊汤点“一碗羊杂汤”
老杨羊汤已收到,顾客点了:一碗羊杂汤
-----------------------------------
在绝味鸭脖点“一斤鸭脖”
绝味鸭脖未开店

四、常见应用场景

  • 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
  • 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。