天天看点

js设计模式【详解】—— 中介者模式

目录

​​中介者模式的定义​​

​​中介者模式和观察者模式的区别​​

​​中介者模式和外观模式的区别​​

​​演示范例——中介者模式​​

中介者模式的定义

中介者模式(Mediator):用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立地改变它们之间的交互。

类型:行为模式

用途:解除对象与对象之间的紧耦合关系

现实中的中介者模式:机场指挥塔就是中介者,它控制着飞机的起飞和降落,因为所有的沟通都是从飞机向塔台汇报来完成的,而不是飞机之前相互沟通。

使用场景:如果对象之间的复杂耦合确实导致调用和维护出现了困难,而且这些耦合度随项目的变化呈指数增长曲线,那我们就可以考虑用中介者模式来重构代码。

优点:中介者模式使各个对象之间得以解耦,以中介者和对象之间的一对多关系取代了对象之间的网状多对多关系。各个对象只需关注自身功能的实现,对象之间的交互关系交给了中介者对象来实现和维护。

js设计模式【详解】—— 中介者模式
js设计模式【详解】—— 中介者模式

缺点:系统中会新增一个中介者对象,因为对象之间交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象经常是巨大的。中介者对象自身往往就是一个难以维护的对象。

中介者模式和观察者模式的区别

  • 观察者模式(​​javascript:void(0)​​)没有封装约束的单个对象,相反,观察者Observer和具体类Subject是一起配合来维护约束的,沟通是通过多个观察者和多个具体类来交互的:每个具体类通常包含多个观察者,而有时候具体类里的一个观察者也是另一个观察者的具体类。
  • 中介者模式所做的不是简单的分发,而是扮演着维护这些约束的职责。

中介者模式和外观模式的区别

  • 中介者所做的是在模块之间进行通信,是多向的
  • 外观模式(​​javascript:void(0)​​)只是为某一个模块或系统定义简单的接口而不添加额外的功能。系统中的其它模块和外观模式这个概念没有直接联系,可以认为是单向性。

演示范例——中介者模式

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

<body>
选择颜色: <select id="colorSelect">
<option value="">请选择</option>
<option value="red">红色</option>
<option value="blue">蓝色</option>
</select>
选择内存: <select id="memorySelect">
<option value="">请选择</option>
<option value="32G">32G</option>
<option value="16G">16G</option>
</select>
输入购买数量: <input type="text" id="numberInput"/><br/>
您选择了颜色: <div id="colorInfo"></div><br/>
您选择了内存: <div id="memoryInfo"></div><br/>
您输入了数量: <div id="numberInfo"></div><br/>
<button id="nextBtn" disabled="true">请选择手机颜色和购买数量</button>
</body>      
// 手机库存(从后端获取得到)
var goods = {
    "red|32G": 3,
    "red|16G": 0,
    "blue|32G": 1,
    "blue|16G": 6
};

// 中介者
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 ( ( ( number - 0 ) | 0 ) !== number - 0 ){ // 输入购买数量是否为正整数
                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 );
};