学习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 相关文章推荐
Javascript this指针
Jul 30 Javascript
JQuery中html()方法使用不当带来的陷阱
Apr 07 Javascript
js 利用className得到对象的实现代码
Nov 15 Javascript
js跳转页面方法实现汇总
Feb 11 Javascript
JS判断字符串长度的5个方法(区分中文和英文)
Mar 18 Javascript
JavaScript中的包装对象介绍
Jan 27 Javascript
JavaScript声明变量名的语法规则
Jul 10 Javascript
fastclick插件导致日期(input[type=&quot;date&quot;])控件无法被触发该如何解决
Nov 09 Javascript
深入理解(function(){... })();
Aug 16 Javascript
使用smartupload组件实现jsp+jdbc上传下载文件实例解析
Jan 05 Javascript
微信小程序实现指定显示行数多余文字去掉用省略号代替
Jul 25 Javascript
RxJS在TypeScript中的简单使用详解
Apr 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
探讨各种PHP字符串函数的总结分析
2013/06/05 PHP
smarty模板引擎从配置文件中获取数据的方法
2015/01/22 PHP
thinkphp多表查询两表有重复相同字段的完美解决方法
2016/09/22 PHP
php7 图形用户界面GUI 开发示例
2020/02/22 PHP
Javascript 键盘keyCode键码值表
2009/12/24 Javascript
JavaScript导出Excel实例详解
2014/11/25 Javascript
基于javascript实现窗口抖动效果
2016/01/03 Javascript
基于jQuery实现仿微博发布框字数提示
2016/07/27 Javascript
Angular 4.0学习教程之架构详解
2017/09/12 Javascript
详解vue-cli快速构建vue应用并实现webpack打包
2017/12/13 Javascript
jQuery实现DIV响应鼠标滑过由下向上展开效果示例【测试可用】
2018/04/26 jQuery
vue.js与后台数据交互的实例讲解
2018/08/08 Javascript
element-ui 中的table的列隐藏问题解决
2018/08/24 Javascript
详解将微信小程序接口Promise化并使用async函数
2019/08/05 Javascript
代码块高亮可复制显示js插件highlight.js+clipboard.js整合
2021/02/15 Javascript
简单介绍Python中的JSON模块
2015/04/08 Python
Python计算一个文件里字数的方法
2015/06/15 Python
Python基础中所出现的异常报错总结
2016/11/19 Python
python中模块的__all__属性详解
2017/10/26 Python
Python cookbook(字符串与文本)针对任意多的分隔符拆分字符串操作示例
2018/04/19 Python
python矩阵转换为一维数组的实例
2018/06/05 Python
Selenium元素的常用操作方法分析
2018/08/10 Python
django配置连接数据库及原生sql语句的使用方法
2019/03/03 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
Jupyter加载文件的实现方法
2020/04/14 Python
详解如何使用Pytest进行自动化测试
2021/01/14 Python
使用spring mvc+localResizeIMG实现HTML5端图片压缩上传的功能
2016/12/16 HTML / CSS
丹尼尔惠灵顿手表天猫官方旗舰店:Daniel Wellington
2017/08/25 全球购物
使用C#编写创建一个线程的代码
2013/01/22 面试题
保健品市场营销方案
2014/03/31 职场文书
战友聚会主持词
2014/04/02 职场文书
住院医师规范化培训实施方案
2014/06/12 职场文书
授权委托书范本(单位)
2014/09/28 职场文书
毕业纪念册寄语大全
2015/02/26 职场文书
2015年新农合工作总结
2015/03/30 职场文书
处世之道:关于真诚相待的名言推荐
2019/12/02 职场文书