Fork me on GitHub

中介者模式


中介者模式的作用就是解除对象与对象之间的紧耦合关系。增加一个中介者对象后,所有的相关对象都可以通过中介者对象来通信,而不是相互引用,所以当一个对象发生改变时,只需要通知中介者对象即可。中介者模式使网状的多对多关系变成了相对简单的一对多关系。

中介者模式的例子–购买商品

假如我们正在编写一个手机购买的页面,在购买流程中,可以选择手机的颜色以及输入购买数量,同时页面中有两个展示区域,分别向用户展示选择好的颜色和数量。
show the code:

var colorSelect = document.getElemmentById('colorSelect'),
    numberInput= document.getElemmentById('numberInput'),
    colorInfo= document.getElemmentById('colorInfo'),
    numberInfo = document.getElemmentById('numberInfo '),
    nextBtn = document.getElemmentById('nextBtn ');

var goods = { //手机库存
    "red": 3,
    "blue": 6
};
//选择颜色时候
colorSelect.onchange = function() {
    var color = this.value, //颜色
        number = numberInput.value, //数量
        stock = goods[color]; //该颜色手机对应的当前库存
    colorInfo.innerHTML = color;
    if (!color) {
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择手机颜色';
        return;
    }
    if (((number - 0) | 0) !== number - 0) { //用户输入的购买数量是否为正整数
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请输入正确的购买数量';
        return;
    }
    if (number > stock) { //库存是否充足
        nextBtn.disabled = true;
        nextBtn.innerHTML = '库存不足';
        return;
    }
    nextBtn.disable = false;
    nextBtn.innerHTML = '放入购物车';
}

//选择数量的时候
numberInput.oninput = function() {
    var color = this.value, //颜色
        number = numberInput.value, //数量
        stock = goods[color]; //该颜色手机对应的当前库存
    numberInfo.innerHTML = number;
    if (!color) {
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请选择手机颜色';
        return;
    }
    if (((number - 0) | 0) !== number - 0) { //用户输入的购买数量是否为正整数
        nextBtn.disabled = true;
        nextBtn.innerHTML = '请输入正确的购买数量';
        return;
    }
    if (number > stock) { //库存是否充足
        nextBtn.disabled = true;
        nextBtn.innerHTML = '库存不足';
        return;
    }
    nextBtn.disable = false;
    nextBtn.innerHTML = '放入购物车';
}

以上代码看起来能运行了,但是加入我们对json数据对象做了一些修改,例如:

var goods = {
    "red|32G": 3,
    "red|16G": 3,
    "blue|32G": 3,
    "blue|16G": 3
}

那样子我们要对numberInputcolorSelect进行改写,而且添加的内容大同小异但是很繁复,每个对象都是耦合在一起的,如果其中一个任何做了改变,另外的都要进行改变,这样很麻烦

引入中介者

var mediator = (function() {
    var colorSelect = document.getElemmentById('colorSelect'),
        numberInput= document.getElemmentById('numberInput'),
        colorInfo= document.getElemmentById('colorInfo'),
        numberInfo = document.getElemmentById('numberInfo '),
        nextBtn = document.getElemmentById('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.disable = false;
            nextBtn.innerHTML = '放入购物车';
        }
    }    
})();
//事件函数
colorSelect.onchange = function() {
    mediator.changed(this);
};
memorySelect.onchange = function() {
    mediator.changed(this);
};
numberInput.oninput = function() {
    mediator.changed(this);
};

这样,假如某天我们又要新增什么需求,就只要能够稍稍改动mediator对象即可。

总结

最后来个总结:
中介者模式使各个对象之间得以解耦,以中介者和对象之间的一对多关系取代了对象之间的网状多对多关系,各个对象只需关注自身功能的实现。但是这样也存在一个缺点,系统中会新增一个中介者对象,因为对象交互的复杂性,转移成了中介者对象的复杂性,使得中介者对象通常是巨大的。中介者对象自身往往就是一个难以维护的对象。

我知道是不会有人点的,但万一有人想不开呢?