学习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初学者应注意的七个细节小结
Jan 30 Javascript
js点击列表文字对应该行显示背景颜色的实现代码
Aug 05 Javascript
JQuery移动页面开发之屏幕方向改变与滚屏的实现
Dec 03 Javascript
javascript中加var和不加var的区别 你真的懂吗
Jan 06 Javascript
JQuery查找子元素find()和遍历集合each的方法总结
Mar 07 Javascript
详解AngularJS 路由 resolve用法
Apr 24 Javascript
JavaScript中双向数据绑定详解
May 03 Javascript
小程序hover-class点击态效果实现
Feb 26 Javascript
vue滚动tab跟随切换效果
Jun 29 Javascript
vue+element树组件 实现树懒加载的过程详解
Oct 21 Javascript
google广告之另类js调用实现代码
Aug 22 Javascript
一篇文章看懂JavaScript中的回调
Jan 05 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中jpgraph类库的使用介绍
2013/08/08 PHP
Thinkphp的volist标签嵌套循环使用教程
2014/07/08 PHP
PHP配置把错误日志以邮件方式发送方法(Windows系统)
2015/06/23 PHP
yii2.0整合阿里云oss删除单个文件的方法
2017/09/19 PHP
PHP实现的服务器一致性hash分布算法示例
2018/08/09 PHP
在网页中控制wmplayer播放器
2006/07/01 Javascript
载入进度条 效果
2006/07/08 Javascript
JavaScript对象的property属性详解
2014/04/01 Javascript
Javascript玩转继承(一)
2014/05/08 Javascript
异步JavaScript编程中的Promise使用方法
2015/07/28 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
JS实现仿PS的调色板效果完整实例
2016/12/21 Javascript
详解angular2实现ng2-router 路由和嵌套路由
2017/03/24 Javascript
微信小程序中做用户登录与登录态维护的实现详解
2017/05/17 Javascript
JQuery属性操作与循环用法示例
2019/05/15 jQuery
JS获取动态添加元素的方法详解
2019/07/31 Javascript
基于JavaScript 实现拖放功能
2019/09/12 Javascript
Vue 解决在element中使用$notify在提示信息中换行问题
2020/11/11 Javascript
Python全局变量用法实例分析
2016/07/19 Python
python写入已存在的excel数据实例
2018/05/03 Python
Django 限制用户访问频率的中间件的实现
2018/08/23 Python
Python中Proxypool库的安装与配置
2018/10/19 Python
使用Python和百度语音识别生成视频字幕的实现
2020/04/09 Python
Pycharm自带Git实现版本管理的方法步骤
2020/09/18 Python
HTML5 input元素类型:email及url介绍
2013/08/13 HTML / CSS
专门经营化妆刷的美国彩妆品牌:Sigma Beauty
2017/09/11 全球购物
Three Graces London官网:英国奢侈品牌
2021/03/18 全球购物
建筑设计所实习生自我鉴定
2013/09/25 职场文书
文明青少年标兵事迹材料
2014/01/28 职场文书
车间安全生产标语
2014/06/06 职场文书
中药学自荐信
2014/06/15 职场文书
2014年幼儿园班级工作总结
2014/12/17 职场文书
师德师风学习材料
2014/12/19 职场文书
Python 匹配文本并在其上一行追加文本
2022/05/11 Python
SQL中的连接查询详解
2022/06/21 SQL Server
Python+DeOldify实现老照片上色功能
2022/06/21 Python