学习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 相关文章推荐
innerText 使用示例
Jan 23 Javascript
Javascript快速排序算法详解
Dec 03 Javascript
javascript中createElement的两种创建方式
May 14 Javascript
JavaScript多并发问题如何处理
Oct 28 Javascript
JCrop+ajaxUpload 图像切割上传的实例代码
Jul 20 Javascript
js实现本地图片文件拖拽效果
Jul 18 Javascript
解决Vue2.0自带浏览器里无法打开的原因(兼容处理)
Jul 28 Javascript
微信小程序之数据缓存的实例详解
Sep 29 Javascript
jackson解析json字符串,首字母大写会自动转为小写的方法
Dec 22 Javascript
JS判断两个数组或对象是否相同的方法示例
Feb 28 Javascript
Electron + vue 打包桌面操作流程详解
Jun 24 Javascript
Vue 使用typescript如何优雅的调用swagger API
Sep 01 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
php中文本操作的类
2007/03/17 PHP
PHP 面向对象 PHP5 中的常量
2010/05/05 PHP
php生成EAN_13标准条形码实例
2013/11/13 PHP
php中的strpos使用示例
2014/02/27 PHP
php中有关字符串的4个函数substr、strrchr、strstr、ereg介绍和使用例子
2014/04/24 PHP
PHP+jQuery+Ajax实现分页效果 jPaginate插件的应用
2015/10/09 PHP
PHP二维关联数组的遍历方式(实例讲解)
2017/10/18 PHP
根据分辩率调用不同的CSS.
2007/01/08 Javascript
静态页面下用javascript操作ACCESS数据库(读增改删)的代码
2007/05/14 Javascript
js实现ifram取父窗口URL地址的方法
2015/02/09 Javascript
JavaScript获取DOM元素的11种方法总结
2015/04/25 Javascript
js面向对象之常见创建对象的几种方式(工厂模式、构造函数模式、原型模式)
2015/11/09 Javascript
一系列Bootstrap导航条使用方法分享
2016/04/29 Javascript
深入分析javascript中console命令
2016/08/14 Javascript
原生js实现类似fullpage的单页/全屏滚动
2017/01/22 Javascript
浅谈JS中的常用选择器及属性、方法的调用
2017/07/28 Javascript
结合mint-ui移动端下拉加载实践方法总结
2017/11/08 Javascript
Vuex入门到上手教程
2018/06/20 Javascript
python中将阿拉伯数字转换成中文的实现代码
2011/05/19 Python
python利用hook技术破解https的实例代码
2013/03/25 Python
python基础教程之简单入门说明(变量和控制语言使用方法)
2014/03/25 Python
你所不知道的Python奇技淫巧13招【实用】
2016/12/14 Python
Python设计模式之代理模式简单示例
2018/01/09 Python
Python带动态参数功能的sqlite工具类
2018/05/26 Python
Python编写合并字典并实现敏感目录的小脚本
2019/02/26 Python
完美解决pycharm导入自己写的py文件爆红问题
2020/02/12 Python
Python实现在Windows平台修改文件属性
2020/03/05 Python
python如何实现word批量转HTML
2020/09/30 Python
实例讲解使用SVG制作loading加载动画的方法
2016/04/05 HTML / CSS
Mytheresa美国官网:德国知名的女性奢侈品电商
2017/05/27 全球购物
美国餐厅用品和厨房设备批发网站:KaTom Restaurant Supply
2018/01/27 全球购物
Radley英国官网:英国莱德利小狗包
2019/03/21 全球购物
美国手工艺品市场的领导者:Annie’s
2019/04/04 全球购物
校园运动会广播稿
2015/08/19 职场文书
关于python类SortedList详解
2021/09/04 Python
VMware虚拟机安装 Windows Server 2022的详细图文教程
2022/09/23 Servers