zoukankan      html  css  js  c++  java
  • 设计模式-中介者模式

    面向对象设计鼓励把对象划分成更小的粒度,每个对象负责一个特定的功能,这有助于增强对象的可复用性。但由于这些细粒度对象之间的联系激增,又有可能会反过来降低它们的可复用性。当程序的规模增大,对象会越来越多,它们之间的关系也越来越复杂,难免会形成网状的交叉引用。如图

    中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都通过中介者对象来通信,而不是互相引用,所以当一个对象发生改变时,只需要通知中介者对象即可。中介者使各对象之间耦合松散,而且可以独立地改变它们之间的交互。如图

    假设我们正在编写一个手机购买的页面,在购买流程中,可以选择手机的颜色、内存大小以及输入购买数量,同时页面中有三个展示区域,分别向用户展示刚刚选择好的颜色、内存和数量。还有一个按钮动态显示下一步的操作,我们需要查询该颜色手机对应的库存,如果库存数量少于这次的购买数量,按钮将被禁用并且显示库存不足,反之按钮可以点击并且显示放入购物车

    <!DOCTYPE html>
    <html>
    <body>
      <div>
        颜色: <select id="colorSelect">
          <option value="">请选择</option>
          <option value="red">红色</option>
          <option value="blue">蓝色</option>
        </select>
        内存: <select id="memorySelect">
          <option value="">请选择</option>
          <option value="16G">16G</option>
          <option value="32G">32G</option>
        </select>
        数量: <input type="number" id="numberInput" />
      </div>
      您选择了颜色: <div id="colorInfo"></div><br />
      您选择了内存: <div id="memoryInfo"></div><br />
      您输入了数量: <div id="numberInfo"></div><br />
      <button id="nextBtn" disabled="true">请选择手机颜色和购买数量</button>
    </body>
    <script>
    var goods = { // 手机库存
      "red|32G": 3,
      "red|16G": 0,
      "blue|32G": 1,
      "blue|16G": 6
    };
    
      // {"red|32G": 3, "red|16G": 0,"blue|32G": 1,"blue|16G": 6}
      // [['red', 'blue'], ['32G', '16G']]
    function getSku(obj) {
      var keys = Object.keys(obj),
        skuType = (keys.length && keys[0].split('|')) || [],
        arr = [];
      skuType.forEach(function(item, index){
        arr.push([]); // 根据SKU类型,确认二维数组数量
        keys.forEach(function(item) {
          // 第一个数组存储颜色,第二数组存储内存,依次类推
          var sku = item.split('|')[index]
          if(arr[index].indexOf(sku) == -1) { 
            arr[index].push(sku)
          }
        })
      })
      return arr;
    }
    
    console.log(getSku(goods))
    // 中介者
    var mediator = (function() {
      var colorSelect = document.getElementById('colorSelect'),
        memorySelect = document.getElementById('memorySelect'),
        numberInput = document.getElementById('numberInput'),
        colorInfo = document.getElementById('colorInfo'),
        memoryInfo = document.getElementById('memoryInfo'),
        numberInfo = document.getElementById('numberInfo'),
        nextBtn = document.getElementById('nextBtn');
      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) {
            memoryInfo.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 (!(/(^[1-9]d*$)/.test(number))) {
            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);
    };
    </script>
    </html>
    

    使用中介者模式的优势很明显,颜色、内存和数量选择之间没有复杂的相互引用,所有的逻辑操作都由mediator对象集中管理。如果后期SKU又新增了CPU选择项,只需要稍微改动mediator对象

    var goods = { // 手机库存
      "red|32G|800": 3, // 颜色 red,内存 32G,cpu800,对应库存数量为 3
      "red|16G|801": 0,
      "blue|32G|800": 1,
      "blue|16G|801": 6
    };
    
    var mediator = (function() {
      // 略
      var cpuSelect = document.getElementById('cpuSelect');
      return {
        change: function(obj) {
          // 略
          var cpu = cpuSelect.value,
            stock = goods[color + '|' + memory + '|' + cpu];
          if (obj === cpuSelect) {
            cpuInfo.innerHTML = cpu;
          }
          // 略
        }
      }
    })();
    
    常用网站: SegmentFault | GitHub | 掘金社区
  • 相关阅读:
    video兼容ie,ckplayer网页播放器
    边框在2个边,不重叠不接触的情况下是梯形。
    【Unity】关于屏幕自适应的思路
    【Unity】鼠标指向某物体,在其上显示物体的名字等等等等信息
    【C#】关于左移/右移运算符的使用
    【Unity】鼠标点选物体
    Python time和datetime模块
    Python 模块之间的调用
    SaltStack 使用pillar安装配置管理zabbix
    SaltStack 实践课程一
  • 原文地址:https://www.cnblogs.com/yesyes/p/15375975.html
Copyright © 2011-2022 走看看