学习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 Discuz代码中的msn聊天小功能
May 25 Javascript
JS request函数 用来获取url参数
May 17 Javascript
前台js改变Session的值(用ajax实现)
Dec 28 Javascript
javascript单例模式的简单实现方法
Jul 25 Javascript
jQuery添加和删除输入文本框标签代码
May 20 Javascript
AngularJS 路由和模板实例及路由地址简化方法(必看)
Jun 24 Javascript
jQuery实现查找链接文字替换属性的方法
Jun 27 Javascript
原生js实现自由拖拽弹窗代码demo
Jun 29 Javascript
Vue中v-for的数据分组实例
Mar 07 Javascript
vue devtools的安装与使用教程
Aug 08 Javascript
layui table设置某一行的字体颜色方法
Sep 05 Javascript
Vue-Cli项目优化操作的实现
Oct 27 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
Laravel中的chunk组块结果集处理与注意问题
2018/08/15 PHP
PDO::errorInfo讲解
2019/01/28 PHP
爆炸式的JS圆形浮动菜单特效代码
2010/03/03 Javascript
分享几个超级震憾的图片特效
2012/01/08 Javascript
3分钟写出来的Jquery版checkbox全选反选功能
2013/10/23 Javascript
javascript间隔刷新的简单实例
2013/11/14 Javascript
JavaScript+CSS控制打印格式示例介绍
2014/01/07 Javascript
AngularJS中的过滤器使用详解
2015/06/16 Javascript
js控制多图左右滚动切换效果代码分享
2015/08/26 Javascript
Angular Js文件上传之form-data
2015/08/28 Javascript
浅析node连接数据库(express+mysql)
2015/11/30 Javascript
javascript this详细介绍
2016/09/19 Javascript
AngularJS $http模块POST请求实现
2017/04/08 Javascript
JavaScript实现跟随滚动缓冲运动广告框
2017/07/15 Javascript
vue-prop父组件向子组件进行传值的方法
2018/03/01 Javascript
浅析vue中的MVVM实现原理
2019/03/04 Javascript
[00:35]DOTA2上海特级锦标赛 MVP.Phx战队宣传片
2016/03/04 DOTA
netbeans7安装python插件的方法图解
2013/12/24 Python
Python字符串处理之count()方法的使用
2015/05/18 Python
Flask框架使用DBUtils模块连接数据库操作示例
2018/07/20 Python
python 多线程对post请求服务器测试并发的方法
2019/06/13 Python
Pandas之Dropna滤除缺失数据的实现方法
2019/06/25 Python
python retrying模块的使用方法详解
2019/09/25 Python
代码总结Python2 和 Python3 字符串的区别
2020/01/28 Python
phpquery中文手册
2021/03/18 PHP
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
团工委书记自荐书范文
2013/12/17 职场文书
员工拾金不昧表扬信
2014/01/09 职场文书
求职简历中自我评价
2014/01/28 职场文书
感恩节活动策划方案
2014/05/16 职场文书
煤矿安全协议书
2014/08/20 职场文书
酒店保洁员岗位职责
2015/02/26 职场文书
销售经理岗位职责范本
2015/04/02 职场文书
业务员岗位职责范本
2015/04/03 职场文书
二审代理词范文
2015/05/25 职场文书
Redis基本数据类型String常用操作命令
2022/06/01 Redis