轻松掌握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 相关文章推荐
JavaScript While 循环基础教程
Apr 05 Javascript
js给onclick事件赋值,动态传参数实例解说
Mar 28 Javascript
jQuery操作select下拉框的text值和value值的方法
May 31 Javascript
Jquery节点遍历next与nextAll方法使用示例
Jul 22 Javascript
javascript关于运动的各种问题经典总结
Apr 27 Javascript
在Javascript中处理数组之toSource()方法的使用
Jun 09 Javascript
JQuery包裹DOM节点的方法
Jun 11 Javascript
easyui tree带checkbox实现单选的简单实例
Nov 07 Javascript
详解JS中遍历语法的比较
Apr 07 Javascript
详解vue.js之绑定class和style的示例代码
Aug 24 Javascript
浅谈vue-router2路由参数注意的问题
Nov 08 Javascript
Vue可自定义tab组件用法实例
Oct 24 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
ThinkPHP控制器间实现相互调用的方法
2014/10/31 PHP
PHP身份证校验码计算方法
2016/08/10 PHP
PHP+Ajax 检测网络是否正常实例详解
2016/12/16 PHP
Thinkphp5框架简单实现钩子(Hook)行为的方法示例
2019/09/03 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
$.format,jquery.format 使用说明
2011/07/13 Javascript
js事件(Event)知识整理
2012/10/11 Javascript
判断一个对象是否为jquery对象的方法
2014/03/12 Javascript
js调用后台、后台调用前台等方法总结
2014/04/17 Javascript
javascript使用shift+click实现选择和反选checkbox的方法
2015/05/04 Javascript
jquery实现弹出层效果实例
2015/05/19 Javascript
jQuery实现右侧显示可向左滑动展示的深色QQ客服效果代码
2015/10/23 Javascript
JS基于构造函数实现的菜单滑动显隐效果【测试可用】
2016/06/21 Javascript
表单元素值获取方式js及java方式的简单实例
2016/10/15 Javascript
Angularjs上传图片实例详解
2017/08/06 Javascript
Vue响应式原理深入解析及注意事项
2017/12/11 Javascript
webpack 打包压缩js和css的方法示例
2018/03/20 Javascript
详解webpack-dev-server的简单使用
2018/04/02 Javascript
vue js秒转天数小时分钟秒的实例代码
2018/08/08 Javascript
详解小程序不同页面之间通讯的解决方案
2018/11/23 Javascript
JS中FileReader类实现文件上传及时预览功能
2020/03/27 Javascript
Python 描述符(Descriptor)入门
2016/11/20 Python
Python元组及文件核心对象类型详解
2018/02/11 Python
Python使用xlwt模块操作Excel的方法详解
2018/03/27 Python
pandas使用get_dummies进行one-hot编码的方法
2018/07/10 Python
python微信公众号之关注公众号自动回复
2018/10/25 Python
pytorch 获取层权重,对特定层注入hook, 提取中间层输出的方法
2019/08/17 Python
Python实现报警信息实时发送至邮箱功能(实例代码)
2019/11/11 Python
使用Python paramiko模块利用多线程实现ssh并发执行操作
2019/12/05 Python
tensorflow生成多个tfrecord文件实例
2020/02/17 Python
Django 博客实现简单的全文搜索的示例代码
2020/02/17 Python
如果Session Bean得Remove方法一直都不被调用会怎么样
2012/07/14 面试题
营销与策划个人求职信
2013/09/22 职场文书
湘江北去观后感
2015/06/15 职场文书
Python OpenCV快速入门教程
2021/04/17 Python
Win11筛选键导致键盘失灵怎么解决? Win11关闭筛选键的技巧
2022/04/08 数码科技