学习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 相关文章推荐
转自Jquery官方 jQuery1.1.3发布,速度提升800%,体积保持20K
Aug 19 Javascript
仅img元素创建后不添加到文档中会执行onload事件的解决方法
Jul 31 Javascript
jQuery如何实现点击页面获得当前点击元素的id或其他信息
Jan 09 Javascript
js打开windows上的可执行文件示例
May 27 Javascript
Javascript闭包用法实例分析
Jan 23 Javascript
JS实现的竖向折叠菜单代码
Oct 21 Javascript
js字符串截取函数slice、substring和substr的比较
May 17 Javascript
jquery动态添加带有样式的HTML标签元素方法
Feb 24 jQuery
Vue插件打包与发布的方法示例
Aug 20 Javascript
微信小程序Flex布局用法深入浅出分析
Apr 25 Javascript
微信小程序 函数防抖 解决重复点击消耗性能问题实现代码
Sep 12 Javascript
Electron 调用命令行(cmd)
Sep 23 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 循环删除无限分类子节点的实现代码
2013/06/21 PHP
如何使用php判断服务器是否是HTTPS连接
2013/07/05 PHP
thinkphp数据查询和遍历数组实例
2014/11/28 PHP
php使用parse_url和parse_str解析URL
2015/02/22 PHP
PHP下载远程文件到本地存储的方法
2015/03/24 PHP
javascript this用法小结
2008/12/19 Javascript
window.parent与window.openner区别介绍
2012/04/12 Javascript
jQuery学习笔记之基础中的基础
2015/01/19 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
jQuery无刷新切换主题皮肤实例讲解
2015/10/21 Javascript
JavaScript观察者模式(经典)
2015/12/09 Javascript
JS获取一个表单字段中多条数据并转化为json格式
2017/10/17 Javascript
Node.js学习教程之HTTP/2服务器推送【译】
2017/10/31 Javascript
详解ES6语法之可迭代协议和迭代器协议
2018/01/13 Javascript
基于openlayers4实现点的扩散效果
2020/08/17 Javascript
Angular实现的进度条功能示例
2018/02/18 Javascript
Vue.js 实现地址管理页面思路详解(地址添加、编辑、删除和设置默认地址)
2019/12/11 Javascript
node.js Promise对象的使用方法实例分析
2019/12/26 Javascript
微信小程序淘宝首页双排图片布局排版代码(推荐)
2020/10/29 Javascript
[52:02]完美世界DOTA2联赛PWL S2 FTD.C vs SZ 第一场 11.27
2020/11/30 DOTA
python 实现文件的递归拷贝实现代码
2012/08/02 Python
Python读取文件内容的三种常用方式及效率比较
2017/10/07 Python
Pycharm自动添加文件头注释和函数注释参数的方法
2020/10/23 Python
阿迪达斯加拿大官网:Adidas加拿大
2016/08/25 全球购物
美国机场停车位预订:About Airport Parking
2018/03/26 全球购物
STAY JAPAN台湾:预订日本民宿
2018/07/22 全球购物
Molly Bracken法国电子商店:法国女性时尚品牌
2019/07/24 全球购物
迪士尼西班牙官方网上商店:ShopDisney西班牙
2020/02/02 全球购物
统计学专业毕业生的自我评价分享
2013/11/28 职场文书
学校食堂标语
2014/10/06 职场文书
2014大学辅导员工作总结
2014/12/02 职场文书
2014小学教师年度考核工作总结
2014/12/03 职场文书
离职感谢信怎么写
2015/01/22 职场文书
2015新员工工作总结范文
2015/10/15 职场文书
Python爬虫之爬取某文库文档数据
2021/04/21 Python
apache虚拟主机配置的三种方式(小结)
2022/07/23 Servers