应用程序,无论其大小,都是由一些单个对象所组成。所有这些对象需要一种方式来实现相互通信,而这种通信在一定程度上不降低可维护性,也不损坏那种安全的改变部分应用程序而不会破坏其余部分的能力。随着应用程序的增长,将添加越来越多的对象。然后在代码重构期间,对象将被删除或重新整理。当对象互相知道太多信息并且直接通信时,这将会导致不良的紧耦合问题。当对象间紧耦合时,很难改变单个对象的同时不影响其他的多个对象。因而,即使对应用程序进行最简单的修改也变得不再容易,而且几乎无法估计修改可能花费的时间。
中介者模式缓解了该问题并促进形成松耦合,而且还有助于提高可维护性。这种模式中,独立的对象之间并不直接通信,而是通过mediator对象。当其中一个对象改变状态后,它将会通知该media投入,而mediator将会把该变化传达到其他应该知道此变化的对象。
示例:
该应用程序是一个游戏程序。其中两名玩家分别给予半分钟的时间用于竞争出谁会比另一个按更多次数的按钮。在比赛中玩家1按1,而玩家2按0。计分板依据当前的得分进行更新。
本例中的对象:
- 玩家1
- 玩家2
- 计分板
- 中介者
中介者知道所有其他对象的信息。它与输入设备进行通信并处理键盘按键事件,并且决定哪个玩家前进了一个回合,随后还将该消息通知给玩家。玩家玩游戏的同时,还要通知中介者他所做的事情。中介者将更新后的分数传达给计分板,计分板随后更新显示的分值。
除了中介者以外,没有对象知道任何其它对象。这种模式使得更新游戏变得非常简便,比如,通过该中介者可以很容易添加一个新的玩家或者另一个显示剩余时间的显示窗口。
player对象是由Player()构造函数所创建的,具有points和name属性。属性中的play方法每次以1递增分数,然后通知中介者。
function Player(name){
this.points = 0;
this.name=name;
}
Player.prototype.play = function(){
this.points += 1;
mediator.played();
};
scoreboard对象中有一个update()方法,在每个玩家按完按键后mediator对象调用该方法。scoreboard对象并不知道任何玩家的接口并且没有保存分数,它仅根据mediator给定的值显示分数:
var scoreboard={
element: document.getElementById("results"),
update:function(score){
var i,msg = "";
for(i in score ){
if(score.hasOwnProperty(i)){
msg += "<p><strong>" + i + "</strong>";
msg += score[i];
msg += "</p>"
}
}
this.element.innerHTML = msg;
}
};
最后让我们看下mediator对象。它首先初始化游戏,在他的setup()方法中创建player对象,然后将这些player对象记录到自己的players属性中。其中,played方法将在每次游戏结束时被player对象调用,该方法更新score哈希表并将其发送到scoreboard中以用于显示分数。最后一个方法为keypress(),它用于处理键盘事件,确定哪个玩家前进了一个回合并通知玩家:
var mediator = {
players : {},
setup : function () {
var players = this.players;
players.home = new Player('Home');
players.guest = new Player("Guest");
},
played: function(){
var players = this.players,
score = {
Home : players.home.points,
Huest : players.guest.points
};
scoreboard.update(score);
},
keyPress : function(e){
e = e ||window.event;
if(e.which === 49 ){
mediator.players.home.play();
return;
}
if(e.which === 48){
mediator.players.guest.play();
return;
}
}
};
mediator.setup();
window.onkeypress = mediator.keyPress;