中介者模式

作者: 姜治宇 | 来源:发表于2020-04-03 21:54 被阅读0次

今天我们聊一下中介者模式。
中介者模式跟观察者模式非常像,不过有一点细微的差别:
观察者是订阅和发布两个动作都要做;而中介者是提前订阅好了,只负责发布。
以自定义事件为例,on是监听一个事件,emit是让这个事件发生,这是观察者模式;而中介者模式并不需要on,只需emit。
看一下代码实现:

let Mediator  = (function(){
    let callbacks = {}
    return {
        register:function(type,action){//订阅
            if(callbacks[type]){
                callbacks[type].push(action)
            } else {
                callbacks[type] = []
                callbacks[type].push(action)
            }
        },
        emit:function(type){//发布
            if(callbacks[type]){
                for(let i=0;i<callbacks[type].length;i++){
                    callbacks[type][i] &&  callbacks[type][i]()
                }
            }
        }
    }
})()

代码还是非常简单的,关键是如何使用?什么场景下使用?
比如在一个复杂的网页下有很多模块,如果要在这个页面加一个效果,你肯定不会写一个函数,然后一个一个模块去调用对吧?这样的工作量不仅巨大而且容易遗漏。
解决问题的思路在于解除模块之间的耦合,最好在不修改其他模块的基础上,添加上这个功能。
假设有这么一个需求:
在用户的订单页,加个设置的需求,用户可以选择——是否显示每项右上方的红色消息提示。

mt.jpeg
页面有三个模块:我的订单,我的钱包,互动签到,其中涉及到消息提示的是前两个。
先写一个显示隐藏的方法:
function showHide(mod,tagName,status){
    //获取模块
    let mod = document.getElementById(mod)
    //获取模块下的标签
    let tag = mod.getElementsByTagName(tagName)

    for(let i=0;i<tag.length;i++){
        tag[i].style.visibility = status
    }
}

然后是选择显示隐藏的动作:

(function(){
    let btn = document.getElementById('hide_btn')//开关按钮
    btn.onchange = function(){
        if(btn.checked){
            showHide('orderMod','span','visible')
            showHide('walletMod','span','visible')
        } else {
            showHide('orderMod','span','hidden')
            showHide('walletMod','span','hidden')
        }
    }

})()

这不就实现了?不挺好的嘛,没用到什么中介者啊?
如果是这样设计,这个设置模块,跟订单和钱包两个模块又产生了耦合。
最好的方案是解除任何模块之间的耦合,这样更便于单元测试与维护。
这时中介者模式就派上了用场:

let Mediator  = (function(){
    let callbacks = {}
    return {
        register:function(type,action){//订阅
            if(callbacks[type]){
                callbacks[type].push(action)
            } else {
                callbacks[type] = []
                callbacks[type].push(action)
            }
        },
        emit:function(type){//发布
            if(callbacks[type]){
                for(let i=0;i<callbacks[type].length;i++){
                    callbacks[type][i] &&  callbacks[type][i]()
                }
            }
        }
    }
})()

//模块下的标签操作
function showHide(mod,tagName,status){
    //获取模块
    let mod = document.getElementById(mod)
    //获取模块下的标签
    let tag = mod.getElementsByTagName(tagName)

    for(let i=0;i<tag.length;i++){
        tag[i].style.visibility = status
    }
}
//提前注册显示事件
Mediator.register('showMsg',function(){
    showHide('orderMod','span','visible')

})
Mediator.register('showMsg',function(){

    showHide('walletMod','span','visible')
})
//提前注册隐藏事件
Mediator.register('hideMsg',function(){
    showHide('orderMod','span','hidden')

})

Mediator.register('hideMsg',function(){
    showHide('walletMod','span','hidden')
})
//设置模块
(function(){
    let btn = document.getElementById('hide_btn')//开关按钮
    btn.onchange = function(){
        if(btn.checked){
            Mediator.emit('showMsg')
        } else {
            Mediator.emit('hideMsg')
        }
    }

})()

这样,设置模块跟其他的模块就彻底解耦了。

相关文章

网友评论

    本文标题:中介者模式

    本文链接:https://www.haomeiwen.com/subject/wyvkphtx.html