轻松掌握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 相关文章推荐
Ajax,UTF-8还是GB2312 eval 还是execScript
Nov 13 Javascript
JS声明变量背后的编译原理剖析
Dec 28 Javascript
非常好用的JsonToString 方法 简单实例
Jul 18 Javascript
js每隔5分钟执行一次ajax请求的实现方法
Nov 27 Javascript
JS版元素周期表实现方法
Aug 05 Javascript
JS+JSP通过img标签调用实现静态页面访问次数统计的方法
Dec 14 Javascript
jQuery DataTables插件自定义Ajax分页实例解析
Apr 28 Javascript
jQuery滚动插件scrollable.js用法分析
May 25 jQuery
jQuery列表检索功能实现代码
Jul 17 jQuery
JS鼠标3次点击事件实现代码及扩展思路
Sep 12 Javascript
详解Node全局变量global模块
Sep 28 Javascript
vscode中Vue别名路径提示的实现
Jul 31 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 用checkbox一次性删除多条记录的方法
2010/02/23 PHP
php 购物车完整实现代码
2014/06/05 PHP
thinkphp,onethink和thinkox中验证码不显示的解决方法分析
2016/06/06 PHP
Docker 如何布置PHP开发环境
2016/06/21 PHP
PHP使用preg_split和explode分割textarea存放内容的方法分析
2017/07/03 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
PHP序列化和反序列化深度剖析实例讲解
2020/12/29 PHP
mouse_on_title.js
2006/08/25 Javascript
javascript引导程序
2008/10/26 Javascript
jquery validate在ie8下的bug解决方法
2013/11/13 Javascript
JS和JQ的event对象区别分析
2014/11/24 Javascript
jquery实现弹出层效果实例
2015/05/19 Javascript
javascript父子页面通讯实例详解
2015/07/17 Javascript
基于JavaScript如何实现私有成员的语法特征及私有成员的实现方式
2015/10/28 Javascript
对象题目的一个坑 理解Javascript对象
2015/12/22 Javascript
理解javascript正则表达式
2016/03/08 Javascript
通过BootStrap实现轮播图的实际应用
2016/09/26 Javascript
基于Cookie常用操作以及属性介绍
2017/09/07 Javascript
node.js中http模块和url模块的简单介绍
2017/10/06 Javascript
bootstrap可编辑下拉框jquery.editable-select
2017/10/12 jQuery
JS实现的简单表单验证功能示例
2017/10/13 Javascript
vue的无缝滚动组件vue-seamless-scroll实例
2017/12/18 Javascript
vue源码nextTick使用及原理解析
2019/08/13 Javascript
python对配置文件.ini进行增删改查操作的方法示例
2017/07/28 Python
Python 200行代码实现一个滑动验证码过程详解
2019/07/11 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
Django 项目布局方法(值得推荐)
2020/03/22 Python
兰芝美国网上商城:购买LANEIGE睡眠面膜等
2017/06/30 全球购物
澳大利亚领先的女性运动服品牌:Lorna Jane
2020/06/19 全球购物
经典C++面试题一
2016/11/06 面试题
Jdbc数据访问技术面试题
2012/03/30 面试题
幼儿园区域活动总结
2014/05/08 职场文书
个人对照检查材料思想汇报(四风问题)
2014/09/25 职场文书
期末复习计划
2015/01/19 职场文书
党员个人自我评价
2015/03/03 职场文书
委托书范本格式
2019/04/18 职场文书