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