js设计模式——观察者模式笔记

一直想学习,so,最近学习了一下,做个笔记加深理解

在JavaScript设计模式这本书中,是将卫星通信来解释这个原理的,当然,照此,我们可以举个例子:

张三去公司A面试,李四也去公司A面试。。。,(这就相当于张三,李四都订阅了公司A),公司A过一段时间就发布通知啦,让张三,李四去公司A面试(公司A发布消息,订阅者收到消息),结果,张三有事不去面试了,这就导致张三不再接受A的消息(张三取消订阅公司A)。

先来个简单栗子:

  1. 要指定一个发布者(公司A);
  2. 给发布者添加一个列表,用于存放回调函数以便通知订阅者;(张三,李四中的函数)
  3. 最后发布通知的时候,发布者会遍历这个列表,依次触发里面存放的订阅者回调函数;(暂不考虑取消订阅)
    let Observer = {};  // 公司A
    Observer.clietList = []; // 招聘者列表

    Observer.subscibe = (fn) => {  // 收集招聘者
        Observer.clietList.push(fn)
    }

    Observer.trigger = (...args) => { //发布消息,依次通知招聘者
        Observer.clietList.forEach((fn) => {
            fn.apply(this, args)
        })
    }

    Observer.subscibe((name) => { // 某人投了A简历
        console.log(`${name}去公司A招聘`)
    })

    Observer.trigger('张三') // 发布消息
     // 输出 张三去公司A招聘

以上就是一个很简单的观察者模式,但是如《JavaScript设计模式》书中栗子而言,我们需要一个消息类型,也就是招聘者门都去A面试,那A有很多岗位,下面以前端为例,类似vue,react这种。而且,为了防止列表的污染,我们和书中一样,将以闭包的方式进行改写

let Observer = (() => {
        // 防止消息队列暴露而被篡改,将消息容器作为静态私有变量保存
        const clietList = [] // 发布者列表
        const subscibe = (key, fn) => {  // 增加订阅者函数
            if (!clietList[key]) {
                clietList[key] = []
            }
            clietList[key].push(fn)
        }

        const trigger = (...args) => {  // 发布消息函数
            let key = args.shift(),
                fns = clietList[key]
            fns.forEach((item, index) => {
                fns[index].apply(this, args)
            })
        }

         const remove = function(key, fn) {
            let fns = clietList[key]
            if (!fns) return;
            if (!fn) {
                clietList[key] = [] //不传fn,则直接清空对应的key订阅集合
            } else {
                fns.forEach((item, index) => {
                    if (item === fn) {
                        fns.splice(index, 1) //  删除订阅者的回调函数
                    }
                })
            }
        }

        return {
            subscibe,
            trigger,
            remove
        }

    })();

调用:

    Observer.subscibe('Vue', fn1 = (time) => {
        console.log(`张三面试时间${time}`)
    })
    Observer.subscibe('React', fn2 = (time) => {
        console.log(`李四面试时间${time}`)
    })
    Observer.subscibe('Vue', fn3 = (time) => {
        console.log(`王五面试时间${time}`)
    })
    Observer.trigger('Vue', '2018-10-16')
    Observer.trigger('React', '2018-10-17')

    Observer.remove('Vue', fn1)

    Observer.trigger('Vue', '2018-10-16')
    Observer.trigger('React', '2018-10-17')

输出:

设计模式书中,还举了两个实际栗子来分别阐述,一般解耦与对象间解耦

我这边就照着文章的三位工程师的栗子写了一下,代码有所不同,但是原理都一样:

开发一个评论功能,工程师A,B,C三位各自开发自己的模块,为防止污染,都以闭包形式。怎么将其联系起来,实现功能。

<div>
    <div id='msg_num'></div>
    <div id='msg'></div>
    <div>
        <input type="text" name="" id='user_input'>
        <button id='user_submit'>提交</button>
    </div>
</div>
function $(id) {
        return document.getElementById(id)
     };

     (function () {
        function addMsgItem(e) {
            console.log(e)
            let text = e.text,
            ul = $('msg'),
            li = document.createElement('li'),
            span = document.createElement('span');
            span.innerHTML = '删除';
            li.innerHTML = text;
            span.onclick = function () {
                ul.removeChild(li);
                Observer.trigger('removeCommentMessage', {
                    num: -1
                })
            }
            li.appendChild(span);
            ul.appendChild(li)  
        }
        Observer.subscibe('addCommentMessage', addMsgItem);
     })();

     (function () {
        function changeMsgNum(e) {
            let num = e.num;
            $('msg_num').innerHTML = parseInt($('msg_num').innerHTML ? $('msg_num').innerHTML : 0) + num;
        }

        Observer.subscibe('addCommentMessage', changeMsgNum);
        Observer.subscibe('removeCommentMessage', changeMsgNum);
     })();

     (function() {
        $('user_submit').onclick = function() {
            let text = $('user_input');
            if (!text.value) {
                alert ('请输入');
                return;
            };
            Observer.trigger('addCommentMessage', {
                text: text.value,
                num: 1
            })
            text.value = '';
        }

     })();

效果:

推荐各位可以去看一看这本书,当然,我也是菜鸟,啃了之后似懂非懂。。。哈哈

猜你喜欢

转载自blog.csdn.net/shentibeitaokong/article/details/83068726