多应用+插件架构,代码干净,支持一键云编译,码云点赞13K star,4.8-4.12 预售价格198元 广告
[TOC] # 中介者模式 解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所有当一个对象发生改变时,只需要通知中介者对象即可。中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。中介者模式使网状的多对多关系变成了相对简单的一对多关系。 ## 中介者模式的例子---泡泡堂游戏 改造前: ```javascript // 定义数组保存所有玩家 var players = []; // 先定义玩家构造函数 function Player(name, teamColor){ this.partners = []; // 队友列表 this.enemies = []; // 敌人列表 this.state = 'live'; // 玩家状态 this.name = name; // 角色名字 this.teamColor = null; // 队伍颜色 }; // 玩家团队胜利 Player.prototype.win = function(){ console.log('winner:' + this.name); }; // 玩家团队失败 Player.prototype.lose = function(){ console.log('loser:' + this.name); }; // 玩家死亡 Player.prototype.die = function(){ var all_dead = true; this.state = 'dead'; // 遍历队友列表 for(var i=0, partner; partner = this.partners[i++];){ if(partner.state !== 'dead'){ all_dead = false; break; } } // 如果队友全部死亡 if(all_dead === true){ this.lose(); // 通知所有队友玩家游戏失败 for(var i=0, partner; partner = this.partners[i++];){ partner.lose(); } // 通知所有敌人游戏胜利 for(var i=0, enemy; enmy = this.enemise[i++];){ enemy.win(); } } }; // 定义一个工厂来创建玩家 var playerFactory = function(name, teamColor){ // 创建新玩家 var newPlayer = new Player(name, teamColor); // 通知所有玩家有新角色加入 for(var i=0,player; player=players[i++];){ if(player.teamColor === newPlayer.teamColor){ // 同一队玩家 player.partners.push(newPlayer); // 互相添加到队友列表 newPlayer.partner.push(player); }else{ player.enemies.push(newPlayer); // 互相添加到敌人列表 newPlayer.enemies.push(player); } } players.push(newPlayer); return newPlayer; }; // 创建8个玩家对象 var player1 = playerFactory('a', 'red'); var player2 = playerFactory('b', 'red'); var player3 = playerFactory('c', 'red'); var player4 = playerFactory('d', 'red'); var player5 = playerFactory('e', 'blue'); var player6 = playerFactory('f', 'blue'); var player7 = playerFactory('g', 'blue'); var player8 = playerFactory('h', 'blue'); ``` 这里每个玩家和其它玩家都是紧紧耦合在一起的。用中介者模式进行改造。 ```javascript function Player(name, teamColor){ this.name = name; // 角色名字 this.teamColor = teamColor; // 队伍颜色 this.state = 'alive'; // 玩家生存状态 } Player.prototype.win = function(){ console.log('winner:' + this.name); }; Player.prototype.lose = function(){ console.log('loser:' + this.name); }; Player.prototype.die = function(){ this.state = 'dead'; playerDirector.ReceiveMessage('playerDead', this); // 给中介者发送消息,玩家死亡 }; Player.prototype.remove = function(){ playerDirector.ReceiveMessage('removePlayer', this); // 给中介者发送消息,移除一个玩家 }; Player.prototype.changeTeam = function(){ playerDirector.ReceiveMessage('changeTeam', this); // 给中介者发送消息,玩家换队 }; var playerFactory = function(name, teamColor){ var newPlayer = new Player(name, teamColor); playerDirector.ReceiveMessage('addPlayer', newPlayer); // 给中介者发送消息,新增玩家 return newPlayer; }; // 实现playerDirector对象 var playDirector = (function(){ var players = {}; // 保存所有玩家 var operations = {}; // 中介者可以执行的操作 // 新增一个玩家 operations.add = function(player){ var teamColor = player.teamColor; players[teamColor] = players[teamColor] || []; players[teamColor].push(player); }; // 移除一个玩家 operations.removePlayer = function(player){ var teamColor = player.teamColor; var teamPlayers = players[teamColor] || []; for(var i=teamPlayers.length - 1; i >= 0 ;i --){ if(teamPlayers[i] === player){ teamPlayers.splice(i, 1); } } }; // 玩家换队 operations.changeTeam = function(player, newTeamColor){ operations.removePlayer(player); // 从原队伍中删除 player.teamColor = newTeamColor; // 换颜色 operations.addPlayer(player); // 新增玩家到新的队伍 } operations.playerDead = function(player){ var teamColor = player.teamColor; var teamPlayer = players[teamColor]; var all_dead = true; // 遍历队友列表 for(var i=0, player; player = teamPlayer[i++];){ if(player.state !== 'dead'){ all_dead = false; break; } } // 如果队友全部死亡 if(all_dead === true){ this.lose(); // 通知所有队友玩家游戏失败 for(var i=0, player; player = teamPlayer[i++];){ player.lose(); } // 通知所有敌人游戏胜利 for(var color in players){ if(color !== teamColor){ var teamPlayers = players[color]; for(var i=0, player; player = teamPlayers[i++];){ player.win(); } } } } } var ReceiveMessage = function(){ var message = Array.prototype.shift.call(arguments); operations[message].apply(this, arguments); }; return { ReciveMessage: ReceiveMessage } })(); // 创建8个玩家对象 var player1 = playerFactory('a', 'red'); var player2 = playerFactory('b', 'red'); var player3 = playerFactory('c', 'red'); var player4 = playerFactory('d', 'red'); var player5 = playerFactory('e', 'blue'); var player6 = playerFactory('f', 'blue'); var player7 = playerFactory('g', 'blue'); var player8 = playerFactory('h', 'blue'); ``` 中介者模式是迎合迪米特法则的一种实现。迪米特法则也叫最少知识原则,是指一个对象应该尽可能少地了解另外的对象(类似不合陌生人说话)。如果对象之间的耦合性太高,一个对象发生改变之后,难免会影响到其他的对象。而在中介者模式里,对象之间几乎不知道彼此的存在,它们只能通过中介者对象来互相影响对方。 中介者模式最大的缺点是系统中会新增一个中介者对象,因为对象之间交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象经常是巨大的。中介者对象自身往往就是一个难以维护的对象。 写程序是为了快速完成项目交付生产,而不是堆砌模式和过渡设计。关键就在于如何去衡量对象之间的耦合程度。如果对象之间的复杂耦合确实导致调用和维护出现了困难,而且这些耦合度随项目的变化呈指数增长曲线,那就可以考虑用中介者模式来重构代码。