学习JavaScript设计模式之中介者模式


Posted in Javascript onJanuary 14, 2016

一、定义

面向对象设计鼓励将行为分布到各个对象中,把对象划分成更小的粒度,有助于增强对象的可复用性。但由于这些细粒度对象之间的联系激增,又可能反过来降低它们的可复用性。
中介者模式的作用就是解除对象与对象之间的紧耦合关系。

二、示例:购买商品

  • 假设我们正在开发一个购买手机的页面,购买流程中,可以选择手机颜色以及输入购买数量,同时页面中可以对应展示输入内容。还有一个按钮动态显示下一步操作(该颜色库存量充足,显示下一步;否则显示库存不足)。
<div>
  <span>请选择颜色</span> 
  <select id="selColor">
    <option value="roseGold">玫瑰金</option>
    <option value="luxuryGold">土豪金</option>
  </select>
</div>
<div>
  <span>请输入购买数量:</span>
  <input type="text" id="selNum" /> 
</div>
<div>
  <span>您选择的颜色为:</span><strong id="conColor"></strong>
  <span>您选择的数量为:</span><strong id="conNum"></strong>
</div>

<button id="nextBtn">加入购物车</button>
// 库存量
var goods = {
  roseGold: 10,
  luxuryGold: 10
};

var colorSelect = document.getElementById("selColor"),
  numberInput = document.getElementById("selNum"),
  colorInfo = document.getElementById("conColor"),
  numberInfo = document.getElementById("conNum"),
  nextBtn = document.getElementById("nextBtn");

colorSelect.onchange = function() {
  var color = colorSelect.value, // 颜色
    number = +numberInput.value, // 数量
    stock = goods[color];    // 对应颜色的库存量

  colorInfo.innerHTML = color;
  if(!color) {
    nextBtn.disabled = true;
    nextBtn.innerHTML = "请选择手机颜色";
    return;
  }

  if(!number || (((number - 0) | 0) !== (number - 0))) {
    nextBtn.disabled = true;
    nextBtn.innerHTML = "请选择手机数量";
    return;
  }

  if( number > stock) {
    nextBtn.disabled = true;
    nextBtn.innerHTML = "库存不足";
    return;
  }

  nextBtn.disabled = false;
  nextBtn.innerHTML = "加入购物车";

};

/* 购买数量做同样处理 */

当页面中新增加另外一个下拉列表框,代表手机内存,上述代码改动面很大。

三、引入中介模式

所有的节点对象只跟中介者通信。
当下拉选择框selColor、selMemory亦或文本框selNum发生了事件行为时,仅通知中介者它们被改变了,同时把自己当做参数传入中介者,以便中介者辨别是谁发生了改变,剩下的事情交给中介者对象来完成。

<div>
  <span>请选择颜色:</span> 
  <select id="selColor">
    <option value="roseGold">玫瑰金</option>
    <option value="luxuryGold">土豪金</option>
  </select>
</div>
<div>
  <span>请选择内存:</span>
  <select id="selMemory">
    <option value="16G">16G</option>
    <option value="64G">64G</option>
  </select>
</div>
<div>
  <span>请输入购买数量:</span>
  <input type="text" id="selNum" /> 
</div>
<div>
  <span>您选择的颜色为:</span><strong id="conColor"></strong>
  <span>您选择的内存为:</span><strong id="conMemory"></strong>
  <span>您选择的数量为:</span><strong id="conNum"></strong>
</div>

<button id="nextBtn">加入购物车</button>
// 库存量
var goods = {
  "roseGold|16G": 10,
  "roseGold|32G": 10,
  "luxuryGold|16G": 10,
  "luxuryGold|32G": 10
};

var colorSelect = document.getElementById("selColor"),
    memorySelect = document.getElementById("selMemory"),
    numberInput = document.getElementById("selNum"),
    colorInfo = document.getElementById("conColor"),
    memeryInfo = document.getElementById("conMemory"),
    numberInfo = document.getElementById("conNum"),
    nextBtn = document.getElementById("nextBtn");

var mediator = (function() {
  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) {
        memeryInfo.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 || (((number - 0) | 0) !== (number - 0))) {
        nextBtn.disabled = true;
        nextBtn.innerHTML = "请选择手机数量";
        return;
      }

      if( number > stock) {
        nextBtn.disabled = true;
        nextBtn.innerHTML = "库存不足";
        return;
      }

      nextBtn.disabled = false;
      nextBtn.innerHTML = "加入购物车";
    }
  };
})();

// 事件函数
colorSelect.onchange = function() {
  mediator.changed(this);
};
memorySelect.onchange = function() {
  mediator.changed(this);
};
numberInput.oninput = function() {
  mediator.changed(this);
}

中介者模式是迎合迪米特法则的一种实现。迪米特法则也叫最少知识原则,是指一个对象应该尽可能少地了解另外的对象。避免“城门失火,殃及鱼池”。

缺点:最大的缺点是系统中会增加一个中介对象,因为对象之间交互的复杂性,转移成了中介对象的复杂性,使得中介者对象经常是巨大的,很难维护。

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

希望本文所述对大家学习javascript程序设计有所帮助。

Javascript 相关文章推荐
简单三步,搞掂内存泄漏
Mar 10 Javascript
javascript firefox不显示本地预览图片问题的解决方法
Nov 12 Javascript
举例讲解JavaScript中关于对象操作的相关知识
Nov 16 Javascript
jQuery图片切换动画效果
Feb 28 Javascript
js判断手机系统是android还是ios
Mar 07 Javascript
微信小程序 下拉菜单简单实例
Apr 13 Javascript
微信小程序开发之实现自定义Toast弹框
Jun 08 Javascript
基于JavaScript实现前端数据多条件筛选功能
Aug 19 Javascript
通过js控制时间,一秒一秒自己动的实例
Oct 25 Javascript
微信小程序拼接图片链接无底洞深入探究
Sep 03 Javascript
jQuery实现倒计时功能完整示例
Jun 01 jQuery
vue切换菜单取消未完成接口请求的案例
Nov 13 Javascript
轻松实现jquery手风琴效果
Jan 14 #Javascript
jQuery取得iframe中元素的常用方法详解
Jan 14 #Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
Jan 14 #Javascript
分享网页检测摇一摇实例代码
Jan 14 #Javascript
jquery淡入淡出效果简单实例
Jan 14 #Javascript
jQuery实现的左右移动焦点图效果
Jan 14 #Javascript
详解JavaScript中的构造器Constructor模式
Jan 14 #Javascript
You might like
mysql 字段类型说明
2007/04/27 PHP
PHP判断搜索引擎蜘蛛并自动记忆到文件的代码
2012/02/04 PHP
适合PHP初学者阅读的4本经典书籍
2016/09/23 PHP
thinkphp 字母函数详解T/I/N/D/M/A/R/U
2017/04/03 PHP
PHP实现批量清空删除指定文件夹所有内容的方法
2017/05/30 PHP
微信封装的调用微信签名包的类库
2017/06/08 PHP
PHP htmlspecialchars() 函数实例代码及用法大全
2018/09/18 PHP
PHP实现的62进制转10进制,10进制转62进制函数示例
2019/06/06 PHP
jquery插件 autoComboBox 下拉框
2010/12/22 Javascript
jquery搜索框效果实现方法
2015/01/16 Javascript
简单介绍jsonp 使用小结
2016/01/27 Javascript
浅谈js中调用函数时加不加括号的问题
2016/07/28 Javascript
JQuery控制DIV的选取实现方法
2016/09/18 Javascript
详解js数组的完全随机排列算法
2016/12/16 Javascript
javascript简单链式调用案例分析
2017/05/10 Javascript
Vue实现table上下移动功能示例
2019/02/21 Javascript
jQuery操作事件完整实例分析
2020/01/10 jQuery
JS变量提升原理与用法实例浅析
2020/05/22 Javascript
vue实现编辑器键盘抬起时内容跟随光标距顶位置向上滚动效果
2020/05/28 Javascript
[35:26]DOTA2上海特级锦标赛B组小组赛#2 VG VS Fnatic第三局
2016/02/26 DOTA
Python入门篇之面向对象
2014/10/20 Python
浅谈python和C语言混编的几种方式(推荐)
2017/09/27 Python
pandas计算最大连续间隔的方法
2019/07/04 Python
python修改文件内容的3种方法详解
2019/11/15 Python
tensorflow之获取tensor的shape作为max_pool的ksize实例
2020/01/04 Python
关于TensorFlow新旧版本函数接口变化详解
2020/02/10 Python
澳大利亚最受欢迎的超级商场每日优惠:Catch
2020/11/17 全球购物
如何转换一个字符串到enum值
2014/04/12 面试题
值类型与引用类型有什么不同?请举例说明?并分别列举几种相应的数据类型
2015/10/24 面试题
测绘工程本科生求职信
2013/10/10 职场文书
幼儿教师思想汇报
2014/01/10 职场文书
社区优秀志愿者材料
2014/02/02 职场文书
设计专业毕业生求职信
2014/06/25 职场文书
运动员获奖感言
2014/08/15 职场文书
幼儿园园长新年寄语2015
2014/12/08 职场文书
python 对图片进行简单的处理
2021/06/23 Python