学习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 相关文章推荐
文字幻灯片
Jun 26 Javascript
JavaScript静态的动态
Sep 18 Javascript
DOM2非标准但却支持很好的几个属性小结
Jan 21 Javascript
jquery通过ajax加载一段文本内容的方法
Jan 15 Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
Nov 30 Javascript
JavaScript动态设置div的样式的方法
Dec 26 Javascript
内容滑动切换效果jquery.hwSlide.js插件封装
Jul 07 Javascript
ES6新特性之Symbol类型用法分析
Mar 31 Javascript
javascript实现table单元格点击展开隐藏效果(实例代码)
Apr 10 Javascript
js数组常用最重要的方法
Feb 04 Javascript
jQuery实现浏览器之间跳转并传递参数功能【支持中文字符】
Mar 28 jQuery
JavaScript函数、闭包、原型、面向对象学习笔记
Sep 06 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的SQL注入过程分析
2012/01/06 PHP
PHP实现腾讯与百度坐标转换
2017/08/05 PHP
特殊字符、常规符号及其代码对照表
2006/06/26 Javascript
jQuery+CSS 半开折叠效果原理及代码(自写)
2013/03/04 Javascript
jQuery Mobile页面跳转后未加载外部JS原因分析及解决
2013/03/18 Javascript
javascript中常用编程知识
2013/04/08 Javascript
js限制文本框只能输入整数或者带小数点的数字
2015/04/27 Javascript
jQuery+HTML5实现手机摇一摇换衣特效
2015/06/05 Javascript
javascript函数式编程程序员的工具集
2015/10/11 Javascript
ajax跨域调用webservice的实现代码
2016/05/09 Javascript
基于Bootstrap实现的下拉菜单手机端不能选择菜单项的原因附解决办法
2016/07/22 Javascript
Bootstrap中表单控件状态(验证状态)
2016/08/04 Javascript
AngularJS学习第二篇 AngularJS依赖注入
2017/02/13 Javascript
vue-resource 拦截器使用详解
2017/02/21 Javascript
nodejs 图片预览和上传的示例代码
2017/09/30 NodeJs
vue2.0+vuex+localStorage代办事项应用实现详解
2018/05/31 Javascript
jQuery实现的简单获取索引功能示例
2018/06/04 jQuery
node.js实现上传文件功能
2019/07/15 Javascript
[52:26]完美世界DOTA2联赛决赛 FTD vs Phoenix 第一场 11.08
2020/11/11 DOTA
python获取局域网占带宽最大3个ip的方法
2015/07/09 Python
python矩阵转换为一维数组的实例
2018/06/05 Python
实例讲解Python中浮点型的基本内容
2019/02/11 Python
python中tkinter的应用:修改字体的实例讲解
2019/07/17 Python
Django中自定义模型管理器(Manager)及方法
2019/09/23 Python
美国性感内衣店:Yandy
2018/06/12 全球购物
网页美工求职信范文
2014/04/17 职场文书
写字楼租赁意向书
2014/07/30 职场文书
高校师德师风自我剖析材料
2014/09/29 职场文书
2014年妇委会工作总结
2014/12/10 职场文书
追悼会答谢词
2015/01/05 职场文书
幼儿园圣诞节活动总结
2015/05/06 职场文书
2016党校培训心得体会
2016/01/07 职场文书
创业计划书之零食店(进口)
2019/09/24 职场文书
慰问信(范文3篇)
2019/10/23 职场文书
MongoDB支持的索引类型
2022/04/11 MongoDB
Docker安装MySql8并远程访问的实现
2022/07/07 Servers