一、概述
中介者模式(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("绝味鸭脖","一斤鸭脖");
}
}
结果输出
在南城香点“一碗馄饨”
南城香已收到,顾客点了:一碗馄饨
-----------------------------------
在老杨羊汤点“一碗羊杂汤”
老杨羊汤已收到,顾客点了:一碗羊杂汤
-----------------------------------
在绝味鸭脖点“一斤鸭脖”
绝味鸭脖未开店
四、常见应用场景
- 系统中对象之间存在复杂的引用关系,产生的相互依赖关系结构混乱且难以理解。
- 一个对象由于引用了其他很多对象并且直接和这些对象通信,导致难以复用该对象。
- 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。