《JavaScript设计模式与开发实践》读书笔记之中介者模式
1. 中介者模式
中介者模式的作用就是用来解除对象与对象之间的紧耦合关系,增加中介者后,所有相关对象都通过中介者来通信,而不再相互引用
1.1中介者模式的例子
以泡泡堂游戏为例,先定义一个玩家构造函数,它有三个原型方法
Player.prototype.win,Player.prototype.lose,Player.prototype.die
当只有两个玩家时,一个玩家死亡时游戏结束,同时通知他的对手胜利
- function Player(name){
- this.name=name;
- this.enemy=null;
- }
- Player.prototype.win=function(){
- console.log(this.name+'won');
- };
- Player.prototype.lose=function(){
- console.log(this.name+'lose');
- };
- Player.prototype.die=function(){
- console.log(this.name+'die');
- };
接下来创建两个玩家
- var player1=new Player('玩家1');
- var player2=new Player('玩家2');
- //设置敌人
- player1.enemy=player2;
- player2.enemy=player1;
- //玩家1死亡时,调用自己的die方法完成一局游戏
- player1.die();
当玩家增加时,每个玩家有了自己的队友和若干敌人
定义一个数组players保存所有的玩家,创建玩家之后,循环players来给每个玩家设置敌人和队友
var players=[];
再改写构造函数Player,使每个玩家对象都增加一些属性,分别是队友列表、敌人列表、玩家当前状态、角色名字以及玩家所在队伍的颜色
- function Player(name,teamColor){
- this.partners=[];
- this.enemies=[];
- this.state='live';
- this.name=name;
- this.teamColor=teamColor;
- }
胜利和失败后,对每个玩家提示结果
- 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;enemy=this.enemies[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.partners.push(player);
- }else{
- player.enemies.push(newPlayer);
- newPlayer.enemies.push(player);
- }
- }
- players.push(newPlayer);
- return newPlayer;
- };
用这段代码来创建8个玩家,分属红蓝两队
- var player1=playerFactory('p1','red');
- var player2=playerFactory('p2','red');
- var player3=playerFactory('p3','red');
- var player4=playerFactory('p4','red');
- var player5=playerFactory('p5','blue');
- var player6=playerFactory('p6','blue');
- var player7=playerFactory('p7','blue');
- var player8=playerFactory('p8','blue');
让红队全部死亡
- player1.die();
- player2.die();
- player3.die();
- player4.die();
此时蓝队玩家胜利
1.2 用中介者模式改造上述示例
上述示例中,每个玩家和其他玩家都是紧耦合在一起,partners,enemies保存着其他玩家对象的引用。当对象状态改变,如死亡时,必须显示遍历通知其他玩家
首先仍然是定义Player构造函数和player对象的原型方法
- function Player(name,teamColor){
- this.name=name;
- this.teamColor=teamColor;
- this.state=state;
- };
- Player.prototype.win=function(){
- console.log(this.name+'won');
- };
- Player.prototype.lose=function(){
- console.log(this.name+'lost');
- };
- //玩家死亡时
- Player.prototype.die=function(){
- this.state='dead';
- playerDirector.ReceiveMessage('playerDead',this);
- };
- //移除玩家
- Player.prototype.remove=function(){
- playerDirector.ReceiveMessage('removePlayer',this);
- };
- //玩家换队
- Player.prototype.changeTeam=function(color){
- playerDirector.ReceiveMessage('changeTeam',this,color);
- };
改写创建玩家对象的工厂函数
- var playerFactory=function(name,teamColor){
- var newPlayer=new Player(name,teamColor);
- playerDirector.ReceiveMessage('addPlayer',newPlayer);
- return newPlayer;
- };
playerDirector开放一个对外暴露的接口ReceiveMessage,负责接收player对象发送的消息,
而player对象发送的时候,总是把自身this作为参数发送给playDirector,以便playerDirector识别消息来自于哪个玩家对象
- var playerDirector=(function(){
- var players={},//保存所有玩家
- operations={};//中介者可以执行的操作
- //新增一个玩家
- operations.addPlayer=function(player){
- var teamColor=player.teamColor
- //如果该颜色的玩家还没有成立队伍,则新成立一个队伍
- players[teamColor]=players[teamColor]||[];
- players[teamColor].push(player);//添加玩家进队伍
- };
- //移除一个玩家
- operations.removePlayer=function(player){
- var teamColor=player.teamColor,
- 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,
- teamPlayers=players[teamColor];
- var all_dead=true;
- for(var i=0,player;player=teamPlayers[i++];){
- if(player.state!='dead'){
- all_dead=false;
- break;
- }
- }
- //如果全部死亡
- if(all_dead===true){
- for(var i=0,player;player=teamPlayers[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{
- ReceiveMessage:ReceiveMessage
- }
- })();
现在除了中介者本身,没有一个玩家知道其他玩家的存在,玩家与玩家之间的耦合关系已经解除
某个玩家的任何操作不需要通知其他买家,只需要给中介者发送一个消息
中介者处理完消息之后,把处理结果反馈给其他玩家
《JavaScript设计模式与开发实践》读书笔记之中介者模式的更多相关文章
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(上)
说来惭愧,4个多月未更新了.4月份以后就开始忙起来了,论文.毕设.毕业旅行等七七八八的事情占据了很多时间,毕业之后开始忙碌的工作,这期间一直想写博客,但是一直没能静下心写.这段时间在看<Java ...
- JavaScript设计模式与开发实践——读书笔记1.高阶函数(下)
上部分主要介绍高阶函数的常见形式,本部分将着重介绍高阶函数的高级应用. 1.currying currying指的是函数柯里化,又称部分求值.一个currying的函数会先接受一些参数,但不立即求值, ...
- Javascript设计模式与开发实践读书笔记(1-3章)
第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用 多态最根本好处在于,你不必询问对象“你是什么类型”而后根据得到的答案调用对象的某个行为--你只管调用行为就好,剩下的一切 ...
- javascript设计模式与开发实践阅读笔记(8)——观察者模式
发布-订阅模式,也叫观察者模式:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 在JavaScript开发中,我们一般用事件模型来替代传统的观察者模式. ...
- javascript设计模式与开发实践阅读笔记(7)——迭代器模式
迭代器模式:指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...
- javascript设计模式与开发实践阅读笔记(6)——代理模式
代理模式:是为一个对象提供一个代用品或占位符,以便控制对它的访问. 代理模式的关键是,当客户不方便直接访问一个对象或者不满足需要的时候,提供一个替身对象来控制对这个对象的访问,客户实际上访问的是替身对 ...
- javascript设计模式与开发实践阅读笔记(4)——单例模式
定义 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点. 具体来说,就是保证有些对象有且只有一个,比如线程池.全局缓存.浏览器中的window 对象等.在js中单例模式用途很广,比如登录 ...
- 《JavaScript设计模式与开发实践》笔记第八章 发布-订阅模式
第八章 发布-订阅模式 发布-订阅模式描述 发布-订阅模式又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. 发布-订阅模式可以广泛应用于 ...
- 《JavaScript设计模式与开发实践》笔记第一章
第一章 面向对象的JavaScript 动态类型语言和鸭子类型 编程语言按照数据类型大体可以分为两类:静态类型语言.动态类型语言. 静态类型语言:在编译时便已确定变量的类型. 优点: 在编译时就能发现 ...
- javascript设计模式与开发实践阅读笔记(5)——策略模式
策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换. 我的理解就是把各种方法封装成函数,同时存在一个可以调用这些方法的公共函数.这样做的好处是可以消化掉内部的分支判断,使代码效率 ...
随机推荐
- boost.asio系列——buffer
创建buffer 在io操作中,对数据的读写大都是在一个缓冲区上进行的,在asio框架中,可以通过asio::buffer函数创建一个缓冲区来提供数据的读写.buffer函数本身并不申请内存,只是提供 ...
- linux系统日志及其rsyslog服务
日志是系统用来记录系统运行时候的一些相关消息的纯文本文件 /var/log下保存着大量的纯文本日志文件 日志的目的是为了保持相关程序的运行状态,错误消息,为了对系统运行进行错误分析使用 1.内核消息 ...
- D3D 练习小框架
自己练习D3D 程序搭的小框架,记录在这里,将来看到好回顾自己独自摸索的苦逼样子. #pragma once #pragma comment(lib,"d3d9.lib") #pr ...
- MySQL 创建函数(Function)
目标 怎么样MySQL创建数据库功能(Function) 语法 CREATE FUNCTION func_name ( [func_parameter] ) //括号是必须的,參数是可选的 RETUR ...
- Java Design Demo -简单的队列-异步多任务队列(java android)
简单的单线程队列 -- 工作的时候遇到劣质打印机.给打印机发消息,打印机就会打印,如果在打印机还在打印的时候,就 再发消息打印,就会出现消息丢失.所以需要给上一个任务一些处理的间隔时间. 单线程的消息 ...
- Spring中的FactoryBean
从SessionFactory说起: 在使用SSH集成开发的时候,我们有时候会在applicationContext.xml中配置Hibernate的信息,以下是配置SessionFactory的一段 ...
- javascript中外部js文件取得自身完整路径得办法
原文:javascript中外部js文件取得自身完整路径得办法 有时候我们需要引入一个外部js文件,这个js文件又需要用到自己的路径或者是所在的目录,别问怎么又这么变态的需求,开发做久了各种奇葩需求也 ...
- Swift - 属性观察者(willSet与didSet)
属性观察者,类似于触发器.用来监视属性的除初始化之外的属性值变化,当属性值发生改变时可以对此作出响应.有如下特点: 1,不仅可以在属性值改变后触发didSet,也可以在属性值改变前触发willSet. ...
- html中的rowspan和colspan
摘自w3school(http://www.w3school.com.cn/tags/att_td_colspan.asp)colspan 属性规定单元格可横跨的列数.<table border ...
- windows程序员进阶系列:《软件调试》之Win32堆的调试支持
Win32堆的调试支持 为了帮助程序员及时发现堆中的问题,堆管理器提供了以下功能来辅助调试. 1:堆尾检查(Heap Tail Check) HTC,在堆尾添加额外的标记信息,用于检测堆块是否溢出. ...