学习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 相关文章推荐
js中字符替换函数String.replace()使用技巧
Aug 14 Javascript
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
Feb 05 Javascript
关于innerHTML后丢失动态绑定的EVENT问题解决方法
May 19 Javascript
js数字转换为float,取N位小数
Feb 08 Javascript
php析构函数的具体用法小结
Mar 11 Javascript
javascript从image转换为base64位编码的String
Jul 29 Javascript
js实现数组转换成json
Jun 26 Javascript
Javascript中常用的检测方法小结
Oct 08 Javascript
bootstrap datetimepicker2.3.11时间插件使用
Nov 19 Javascript
JS获取填报扩展单元格控件的值的解决办法
Jul 14 Javascript
node.js学习之断言assert的使用示例
Sep 28 Javascript
vue 监听键盘回车事件详解 @keyup.enter || @keyup.enter.native
Aug 25 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
apache mysql php 源码编译使用方法
2012/05/03 PHP
PHP实现163邮箱自动发送邮件
2016/03/29 PHP
yii框架搜索分页modle写法
2016/12/19 PHP
laravel 框架执行流程与原理简单分析
2020/02/01 PHP
php实现统计IP数及在线人数的示例代码
2020/07/22 PHP
javascript 上下banner替换具体实现
2013/11/14 Javascript
js中window.open打开一个新的页面
2014/08/10 Javascript
Nodejs实现批量下载妹纸图
2015/05/28 NodeJs
jquery实现选中单选按钮下拉伸缩效果
2015/08/06 Javascript
jQuery表单验证插件解析(推荐)
2016/07/21 Javascript
js实现一个简单的数字时钟效果
2017/03/29 Javascript
ECMAScript6变量的解构赋值实例详解
2017/09/19 Javascript
vue项目中添加单元测试的方法
2018/07/21 Javascript
js使用formData实现批量上传
2020/03/27 Javascript
解决vue打包报错Unexpected token: punc的问题
2020/10/24 Javascript
解决Antd Table表头加Icon和气泡提示的坑
2020/11/17 Javascript
phpsir 开发 一个检测百度关键字网站排名的python 程序
2009/09/17 Python
在Python程序中进行文件读取和写入操作的教程
2015/04/28 Python
简单谈谈python中的lambda表达式
2018/01/19 Python
python 用正则表达式筛选文本信息的实例
2018/06/05 Python
python执行CMD指令,并获取返回的方法
2018/12/19 Python
用python画一只可爱的皮卡丘实例
2019/11/21 Python
Python3 读取Word文件方式
2020/02/13 Python
Python爬虫实现自动登录、签到功能的代码
2020/08/20 Python
HTML5中的Web Notification桌面右下角通知功能的实现
2018/04/19 HTML / CSS
苹果台湾官网:Apple台湾
2019/01/05 全球购物
WINDOWS域的具体实现方式是什么
2014/02/20 面试题
科室工作的个人自我评价
2013/10/30 职场文书
《美丽的黄昏》教学反思
2014/02/28 职场文书
经理任命书模板
2014/06/06 职场文书
党在我心中演讲稿
2014/09/02 职场文书
2014县政府领导班子对照检查材料思想汇报
2014/09/25 职场文书
慈善献爱心倡议书
2015/04/27 职场文书
《将心比心》教学反思
2016/02/23 职场文书
Vue3.0写自定义指令的简单步骤记录
2021/06/27 Vue.js
mysql 乱码 字符集latin1转UTF8
2022/04/19 MySQL