轻松掌握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调试工具汇总
Dec 23 Javascript
javascript实现的字符串与十六进制表示字符串相互转换方法
Jul 17 Javascript
JavaScript中 ES6 generator数据类型详解
Aug 11 Javascript
js制作网站首页图片轮播特效代码
Aug 30 Javascript
js控制台输出的方法(详解)
Nov 26 Javascript
vue实现移动端图片裁剪上传功能
Aug 18 Javascript
基于JavaScript实现评论框展开和隐藏功能
Aug 25 Javascript
Angular弹出模态框的两种方式
Oct 19 Javascript
Vue中父子组件通讯之todolist组件功能开发
May 21 Javascript
点击按钮弹出模态框的一系列操作代码实例
Mar 29 Javascript
深入浅析vue-cli@3.0 使用及配置说明
May 08 Javascript
详细介绍解决vue和jsp结合的方法
Feb 06 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 curl post 时出现的问题解决
2014/01/30 PHP
解决Codeigniter不能上传rar和zip压缩包问题
2014/03/07 PHP
Linux下安装oracle客户端并配置php5.3
2014/10/12 PHP
php中数字、字符与对象判断函数用法实例
2014/11/26 PHP
php自定义类fsocket模拟post或get请求的方法
2015/07/31 PHP
Windows 下安装 swoole 图文教程(php)
2017/06/05 PHP
laravel框架数据库配置及操作数据库示例
2019/10/10 PHP
php抽象方法和普通方法的区别点总结
2019/10/13 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
yii框架结合charjs统计上一年与当前年数据的方法示例
2020/04/04 PHP
国外Lightbox v2.03.3 最新版 下载
2007/10/17 Javascript
jquery插件制作教程 txtHover
2012/08/17 Javascript
一款由jquery实现的整屏切换特效
2014/09/15 Javascript
JavaScript淡入淡出渐变简单实例
2015/08/06 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
2017/06/04 Javascript
jQuery实现定时隐藏对话框的方法分析
2018/02/12 jQuery
vuejs点击class变化的实例
2018/09/05 Javascript
详解如何给React-Router添加路由页面切换时的过渡动画
2019/04/25 Javascript
python调用java模块SmartXLS和jpype修改excel文件的方法
2015/04/28 Python
编写Python爬虫抓取豆瓣电影TOP100及用户头像的方法
2016/01/20 Python
Python正则表达式使用范例分享
2016/12/04 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
Python面向对象之继承和多态用法分析
2019/06/08 Python
Pytorch训练过程出现nan的解决方式
2020/01/02 Python
Windows系统下pycharm中的pip换源
2020/02/23 Python
Python绘图实现台风路径可视化代码实例
2020/10/23 Python
世界上最受欢迎的钓鱼诱饵:Rapala
2019/05/02 全球购物
2014年庆元旦活动方案
2014/02/15 职场文书
二年级班级文化建设方案
2014/05/10 职场文书
校庆标语集锦
2014/06/25 职场文书
公安学专业求职信
2014/07/27 职场文书
五年级学生评语大全
2014/12/26 职场文书
期中考试复习计划
2015/01/19 职场文书
污水处理保证书
2015/05/09 职场文书
关于空气污染危害的感想
2015/08/11 职场文书
2015年店长个人工作总结
2015/10/23 职场文书