7/24 设计模式之中介者模式 Mediator Pattern

2020/3/16 posted in  设计模式 JAVA

类别:行为型设计模式

目的:将数个相互耦合的对象进行解耦,转为只耦合一个中介者对象

完整代码参考:https://1drv.ms/u/s!AquRvPzqx59Ri3aYThIUHA4m6crp?e=6d4aE3

典型场景

在ui界面中,点击一个按钮,这个按钮的状态会影响其它按钮的状态,并改变表格的显示方式,参考如下:

2020-03-16_16-38-13 -1-

场景效果:

  1. 点击居左按钮后,表格左对齐,并且居左按钮高亮,居中、居右按钮取消高亮
  2. 点击居中按钮后,表格居中对齐,并且居中按钮高亮,居左、居右按钮取消高亮
  3. 点击居右按钮后,表格居右对齐,并且居右按钮高亮,居左、居中按钮取消高亮

硬编码

基于以上的场景容易写出下面的代码

3个按钮和表格对象原型如下:

左按钮

public class LeftButton {
    private MiddleButton middleButton;
    private RightButton rightButton;
    private Table table;  
      
    public LeftButton(MiddleButton middleButton, RightButton rightButton, Table table) {
        this.middleButton = middleButton;
        this.rightButton = rightButton;
        this.table = table;
    }

    public void click() {
        this.highlight();
        middleButton.cancelHighlight();
        rightButton.cancelHighlight();
        table.alignLeft();
    }

    public void highlight() {
        // 高亮自生
    }
    public void cancelHighlight() {
        // 取消高亮
    }
}

中按钮和右按钮

public class MiddleButton {
    public MiddleButton(LeftButton leftButton, RightButton rightButton, Table table) {
        this.leftButton = leftButton;
        this.rightButton = rightButton;
        this.table = table;
    }
    // 逻辑同LeftButton...
}

public class RightButton {
    public RightButton(LeftButton leftButton, RightButton middleButton, Table table) {
        this.leftButton = leftButton;
        this.middleButton = middleButton;
        this.table = table;
    }
    // 同LeftButton...
}

表格如下:

public class Table {
    public void alignLeft() {
        // 内容左对齐
    }

    public void alignMiddle() {
        // 内容居中对齐
    }

    public void alignRight() {
        // 内容右对齐
    }
}

可以看到

  1. 3个按钮和一个表格对象之间紧耦合了,每个按钮都需要持有对其它按钮的引用
  2. 系统中如果加入一个新按钮,比如复位按钮,所有的按钮和表格都需要为这个新增的按钮进行适配,在组件数量可变的条件下,维护成本巨大(每新增一个组件、所有组件都要为其适配)

模式实现

这个时候就可以引入一个新的中介者对象来集中处理这些组件之间的耦合代码,比如SectionMediator
相互依赖的按钮变更为只依赖中介者即可,在按钮自生状态发生改变时,通知中介者由中介者处理其影响的对象的相关行为调用

拿LeftButton举例更改参考如下:

public class LeftButton implements Component {
    private SectionMediator sectionMediator;

    public LeftButton(SectionMediator sectionMediator) {
        this.sectionMediator = sectionMediator;
    }

    public void click() {
        this.highlight();
        sectionMediator.changed(this);
    }
    // ...
}

可以看到按钮只耦合了一个中介者,并在自生状态改变时(click时)通过调用sectionMediator.changed(this)通知中介者自生状态发生了改变

中介者即处理按钮被点击后相关对象的更新,参考如下:

public class SectionMediator implements Mediator {
    private LeftButton leftButton;
    private MiddleButton middleButton;
    private RightButton rightButton;
    private Table table;

    public SectionMediator(LeftButton leftButton, MiddleButton middleButton, RightButton rightButton, Table table) {
        this.leftButton = leftButton;
        this.middleButton = middleButton;
        this.rightButton = rightButton;
        this.table = table;
    }

    @Override
    public void changed(Component component) {
        if (component == leftButton) {
            middleButton.cancelHighlight();
            rightButton.cancelHighlight();
            table.alignLeft();
        } else if (component == middleButton) {
            leftButton.cancelHighlight();
            rightButton.cancelHighlight();
            table.alignMiddle();
        } else if (component == rightButton) {
            leftButton.cancelHighlight();
            middleButton.cancelHighlight();
            table.alignRight();
        }
    }
}

可以看到在changed方法中,首先对状态变化的主体进行了判断,然后调用影响的对象进行状态变化

UML

为什么中介者模式更好

可以看到中介者去除了对象之间的直接耦合,使得单个对象结构更清晰

一些注意的点

中介者模式的具体实现可以使用观察者模式进行实现

参考资料

  1. https://xuliangzhan.github.io/vxe-table/#/table/base/basic
  2. https://www.geeksforgeeks.org/mediator-design-pattern/