轻松掌握JavaScript中介者模式


Posted in Javascript onAugust 26, 2016

中介者模式的作用就是解除对象与对象之间的紧耦合关系,它也称‘调停者'。所有的对象都通过中介者对象来通信,而不是相互引用,所以当一个对象发生改变时,只需要通知中介者即可。 

如:机场的指挥塔,每架飞机都只需要和指挥塔通信即可,指挥塔知道每架飞机的飞行状况,可以安排所有起降时间,调整航线等 

中介者模式符合迪米特法则,即最少知识原则,指一个对象应该尽可能少地了解另外的对象。如果对象之间的耦合性太高,则改变一个对象,会牵动很多对象,难于维护。当对象耦合很紧时,要修改一个对象而不影响其它的对象是很困难的。 

如果对象之间的复杂耦合确实导致调用和维护出现了困难,而且这些耦合度随项目的变化呈指数增长,那我们就可以考虑用中介者模式来重构代码!中介者通过解耦来提升代码的可维护性。 

例子1:游戏 
玩家对象是通过Player()构造函数来创建的,有自己的points和name属性。原型上的play()方法负责给自己加一分然后通知中介者:

function Player(name) {
  this.points = 0;
  this.name = name;
}
Player.prototype.play = function () {
  this.points += 1;
  mediator.played();
};

scoreboard对象(计分板)有一个update()方法,它会在每次玩家玩完后被中介者调用。计分析根本不知道玩家的任何信息,也不保存分数,它只负责显示中介者给过来的分数:

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()方法中创建游戏者,然后放后players属性以便后续使用。played()方法会被游戏者在每轮玩完后调用,它更新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,
      Guest: players.guest.points
    };
    scoreboard.update(score);
  },
  keypress: function (e) {
    e = e || window.event; // IE
    if (e.which === 49) { // key "1"
      mediator.players.home.play();
      return;
    }
    if (e.which === 48) { // key "0"
      mediator.players.guest.play();
      return;
    }
  }
};

最后一件事是初始化和结束游戏:

// go!
mediator.setup();
window.onkeypress = mediator.keypress;

// game over in 30 seconds
setTimeout(function () {
  window.onkeypress = null;
  alert('Game over!');
}, 30000);

例子2:卖手机

var goods = {  //库存
  'red|32G':3,
  'red|16G':5,
  'blue|32G':3,
  'blue|16G':6
}
//中介者
var mediator = (function(){
  function id(id){
    return document.getElementById(id);
  }
  var colorSelect = id('colorSelect'),
    memorySelect = id('memorySelect'),
    numberInput = id('numberInput'),
    colorInfo = id('colorInfo'),
    memoryInfo = id('memoryInfo'),
    numberInfo = id('numberInfo'),
    nextBtn = id('nextBtn');
  return{
    changed:function(obj){
      var color = colorSelect.value,
        memory = memorySelect.value,
        number = numberInput.value,
        stock = goods[color+'|'+memory];
      if(obj === colorSelect){
        colorInfo.innerHTML = color;
      }else if(obj === memorySelect){
        memoryInfo.innerHTML = memory;
      }else if(obj === numberInput){
        numberInfo.innerHTML = number;
      }
      if(!color){
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择手机颜色';
        return;
      }
      if(!memory){
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择内存大小';
        return;
      }
      if(Number.isInteger(number-0) && number > 0){
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请输入正确的购买数量';
        return;
      }
      nextBtn.disabled = false;
      nextBtn.innerHTML = '放入购物车';
    }
  }
})();
//添加事件
colorSelect.onchange = function(){
  mediator.changed(this);
}
memorySelect.onchange = function(){
  mediator.changed(this);
}
numberInput.onchange = function(){
  mediator.changed(this);
}

参考文献: 《JavaScript模式》 《JavaScript设计模式与开发实践》

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
input 高级限制级用法
Mar 26 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
Dec 12 Javascript
js实现右键自定义菜单
Dec 03 Javascript
概述BootStrap中role=&quot;form&quot;及role作用角色
Dec 08 Javascript
编写React组件项目实践分析
Mar 04 Javascript
浅谈Angular HttpClient简单入门
May 04 Javascript
Vue动态控制input的disabled属性的方法
Jun 26 Javascript
React 项目迁移 Webpack Babel7的实现
Sep 12 Javascript
mpvue将vue项目转换为小程序
Sep 30 Javascript
微信小程序 wepy框架与iview-weapp的用法详解
Apr 10 Javascript
jquery分页优化操作实例分析
Aug 23 jQuery
JavaScript异步操作中串行和并行
Nov 20 Javascript
修改jquery中dialog的title属性方法(推荐)
Aug 26 #Javascript
修改Jquery Dialog 位置的实现方法
Aug 26 #Javascript
在线引用最新jquery文件的实现方法
Aug 26 #Javascript
纯前端JavaScript实现Excel IO案例分享
Aug 26 #Javascript
js时间比较 js计算时间差的简单实现方法
Aug 26 #Javascript
JavaScript toUpperCase()方法使用详解
Aug 26 #Javascript
js遍历map javaScript遍历map的简单实现
Aug 26 #Javascript
You might like
php递归json类实例
2014/12/02 PHP
PHP代码维护,重构变困难的4种原因分析
2016/01/25 PHP
Zend Framework教程之Zend_Registry对象用法分析
2016/03/22 PHP
PHP面试常用算法(推荐)
2016/07/22 PHP
PHP+Ajax简单get验证操作示例
2019/03/02 PHP
jQuery 鼠标经过(hover)事件的延时处理示例
2014/04/14 Javascript
escape函数解决js中ajax传递中文出现乱码问题
2014/10/30 Javascript
JavaScript运动框架 解决防抖动问题、悬浮对联(二)
2017/05/17 Javascript
vue watch监听对象及对应值的变化详解
2018/02/24 Javascript
用ES6的class模仿Vue写一个双向绑定的示例代码
2018/04/20 Javascript
JavaScript实现图片懒加载的方法分析
2018/07/05 Javascript
对angularjs框架下controller间的传值方法详解
2018/10/08 Javascript
js实现黑白div块画空心的图形
2018/12/13 Javascript
Vue动态组件与异步组件实例详解
2019/02/23 Javascript
Nodejs中怎么实现函数的串行执行
2019/03/02 NodeJs
JS PHP字符串截取函数实现原理解析
2020/08/29 Javascript
Ant Design Pro 之 ProTable使用操作
2020/10/31 Javascript
py中的目录与文件判别代码
2008/07/16 Python
Python基础之函数用法实例详解
2014/09/10 Python
Python动态加载模块的3种方法
2014/11/22 Python
Python获取央视节目单的实现代码
2015/07/25 Python
python实现备份目录的方法
2015/08/03 Python
Python中的FTP通信模块ftplib的用法整理
2016/07/08 Python
python中json格式数据输出的简单实现方法
2016/10/31 Python
对python pandas 画移动平均线的方法详解
2018/11/28 Python
Python进阶之全面解读高级特性之切片
2019/02/19 Python
Kali Linux安装ipython2 和 ipython3的方法
2019/07/11 Python
Python中 Global和Nonlocal的用法详解
2020/01/20 Python
python pyqtgraph 保存图片到本地的实例
2020/03/14 Python
python按照list中字典的某key去重的示例代码
2020/10/13 Python
学习雷锋演讲稿
2014/05/10 职场文书
医学生求职自荐书
2014/06/12 职场文书
英语教师求职信范文
2015/03/20 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
2019个人年度目标制定攻略!
2019/07/12 职场文书
python设置 matplotlib 正确显示中文的四种方式
2021/05/10 Python