Java设计模式之从[逛戏中开启宝箱]分析中介者(Mediator)模式

Java设计模式之从[游戏中开启宝箱]分析中介者(Mediator)模式

  假设我们正在设计一个游戏房间,房间里有两个按钮和一个宝箱,如果我们按下了按钮1,则按钮2和宝箱均不可使用;如果我们按下了按钮2,则按钮1和宝箱均不可使用;如果我们打开宝箱,则按钮1不可按下。

  在上面的例子中,我们可以看到两个按钮和一个宝箱之间存在着依赖关系,它们之间的状态是有关联的。假设按钮类叫做Button,宝箱类叫做Chest,我们需要避免Button、Chest之间相互连接,我们应当建立一个中介者类,当Button、Chest的状态发生改变时,应当告诉中介者,由中介者来决定如何改变这些Button和Chest的属性。

Java设计模式之从[逛戏中开启宝箱]分析中介者(Mediator)模式

  一个典型的中介者模式如上图所示。Mediator为中介者的抽象,Colleague为共同协作的对象,如Button、Chest。我们用中介对象来封装一系列对象的交互,中介者使对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

  文章开始的例子实现如下:

interface Director{
    void switchTriggered(Switch sw);
    void createSwitches();
}

class RoomDirector implements Director{
    private Button button1;
    private Button button2;
    private Chest chest;
    public Button getButton1() {
        return button1;
    }
    public void setButton1(Button button1) {
        this.button1 = button1;
    }
    public Button getButton2() {
        return button2;
    }
    public void setButton2(Button button2) {
        this.button2 = button2;
    }
    public Chest getChest() {
        return chest;
    }
    public void setChest(Chest chest) {
        this.chest = chest;
    }
    public void switchTriggered(Switch sw){
        if (sw == button1){
            System.out.println("按钮1被按下");
            button2.setEnabled(false);
            chest.setEnabled(false);
        }
        else if (sw == button2){
            System.out.println("按钮2被按下");
            button1.setEnabled(false);
            chest.setEnabled(false);
        }
        else if (sw == chest){
            System.out.println("箱子被打开");
            button1.setEnabled(false);
        }
    }
    public void createSwitches(){
        button1 = new Button(this);
        button2 = new Button(this);
        chest = new Chest(this);
    }
}

abstract class Switch {
    private boolean enabled = true;
    public boolean isEnabled() {
        return enabled;
    }
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }
    public Switch(Director director) {
        this.director = director;
    }
    private Director director;
    void triggered(){
        director.switchTriggered(this);
    }
}

class Chest extends Switch{
    public Chest(Director director) {
        super(director);
    }
    private boolean opened;
    public boolean isOpened() {
        return opened;
    }
    public void open() {
        if (isEnabled()){
            opened = true;
            triggered();
        } else {
            System.out.println("箱子不可用!");
        }
    }
}

class Button extends Switch{
    public Button(Director director) {
        super(director);
    }
    private boolean push;
    public boolean isPush() {
        return push;
    }
    public void push() {
        if (isEnabled()){
            this.push = true;
            triggered();
        } else {
            System.out.println("按钮不可用!");
        }
    }
}

public class Mediator
{
    public static void main(String[] args) {
        RoomDirector room = new RoomDirector();
        room.createSwitches();
        room.getChest().open();
        room.getButton1().push();
        room.getButton2().push();
    }
}


  Director为一个中介类的抽象,它衍生出了RoomDirector。RoomDirectory里包含了共同协作的3个对象,分别是两个Button和一个Chest,它们均继承于共同协作的Switch类。当Button被按下、Chest被打开的时候,都会调用基类的trigger方法,以通知RoomDirector——"你的某一个对象的状态改变了",紧接着调用RoomDirector里面的switchTriggered方法,来对这3个对象进行操作。在main方法中,我们先打开了箱子,然后按了一下button1,此时button1应该是失效的,再按了一下button2,button2是有效的,因此程序的结果为:

箱子被打开

按钮不可用!

按钮2被按下

  可见,我们所有对象之间的交互动作,都写在了switchTriggered方法中。在RoomDirector这个中介类中,如果需要管理的对象越多,则它会变得越来越复杂。

  在GoF的《设计模式》一书中提到了,通常对话框中的控件存在着依赖关系,如一个特定的文本框内容为空时,某个按钮置灰;列表框的一列选择的一个表目可能会改变一个文本框的内容……那么,我们可以为这些相互依赖的控件建立一个中介类,来使得它们之间的耦合关系变得松散。说白了,其实就是相互依赖的控件状态改变时,向同一个对象发送消息,由这个对象来重新设置这些依赖控件的状态,这也就是中介者模式的中心思想。