Java设计模式之从[逛戏中开启宝箱]分析中介者(Mediator)模式
假设我们正在设计一个游戏房间,房间里有两个按钮和一个宝箱,如果我们按下了按钮1,则按钮2和宝箱均不可使用;如果我们按下了按钮2,则按钮1和宝箱均不可使用;如果我们打开宝箱,则按钮1不可按下。
在上面的例子中,我们可以看到两个按钮和一个宝箱之间存在着依赖关系,它们之间的状态是有关联的。假设按钮类叫做Button,宝箱类叫做Chest,我们需要避免Button、Chest之间相互连接,我们应当建立一个中介者类,当Button、Chest的状态发生改变时,应当告诉中介者,由中介者来决定如何改变这些Button和Chest的属性。
一个典型的中介者模式如上图所示。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的《设计模式》一书中提到了,通常对话框中的控件存在着依赖关系,如一个特定的文本框内容为空时,某个按钮置灰;列表框的一列选择的一个表目可能会改变一个文本框的内容……那么,我们可以为这些相互依赖的控件建立一个中介类,来使得它们之间的耦合关系变得松散。说白了,其实就是相互依赖的控件状态改变时,向同一个对象发送消息,由这个对象来重新设置这些依赖控件的状态,这也就是中介者模式的中心思想。