浅谈我对观察者模式和发布订阅者模式的理解

1,382 阅读3分钟

1 观察者模式(Observer)

定义

对象间一种一对多的依赖关系,当目标对象 Subject 的状态发生改变时,所有依赖它的对象 Observer 都会得到通知。

实质

A男孩和C男孩在M女孩的追求者列表中,当M女孩对追求者列表说我失恋了,追求者列表的A男孩和C男孩收到消息后开心的笑了,因为他们没忍住

特点

  1. M女孩在执行添加、删除、通知操作的时候会通知所有的备胎

代码

        //定义一个女性类
        function Girl() {
            this.backups = []
        }
        //添加一个备胎
        Girl.prototype.add = function (backup) {
            this.backups.push(backup);
        }
        //删除一个备胎
        Girl.prototype.remove = function (backup) {
            let idx = this.backups.findIndex(item => JSON.stringify(item) === JSON.stringify(backup))
            this.backups.splice(idx, 1)
        }
        //通知备胎报名
        Girl.prototype.notify = function () {
            for (let backup of this.backups) {
                backup.enroll.apply(backup, Array.prototype.slice.call(arguments))
            }
        }
        //定义一个男孩类
        function Boy(name) {
            this.name = name;
        }
        Boy.prototype.enroll = function () {
            console.log("我是备胎" + this.name)
        }

        //初始化一个目标女孩
        let girl1 = new Girl();

        //初始化备胎一
        let boy1 = new Boy("longhanghang")
        //初始化备胎二
        let boy2 = new Boy("wangzhiwei")

        //加入女孩的备胎队列
        girl1.add(boy1);
        girl1.add(boy2);

        //通知备胎们报上名来
        girl1.notify();

解读

  1. 女孩和备胎的功能耦合度降低,可以注重自身发展
  2. 备胎男孩被动接受女孩的命令,当女孩发出通知的时候,备胎队列的所有男孩都会收到信息
  3. 备胎男孩无法选择接收消息的类型,只要女孩发出了通知,男孩都会接收到(比如说,男孩只关注女孩的恋爱情况,其他的女孩的动作都不关心,但是女孩所有的动作都会推送过来,男孩都会接收到)

2发布订阅者模式

定义

对象间一种一对多的依赖关系,当目标对象指定的动作发生改变时,订阅该动作的依赖对象会收到相应的通知。

实质

A男孩C男孩是M女主播的粉丝并且开启了主播上线提醒,其中A男孩关注的是女孩在虎牙上的直播,C男孩关注的是女孩在斗鱼上的直播,当M女孩在虎牙上直播的时候会通知到A男孩,当M女孩在斗鱼上面直播的时候会通知到C男孩

特点

  1. 主播(发布者)上不同的平台(事件调度中心)会通知到对应平台的粉丝(订阅者

代码

        //定义一个女主播
        let femaleAnchor = {

            //事件缓存列表(打游戏,唱歌)
            eventList: {},

            //关注主播
            attention: function (event, fn) {
                (this.eventList[event] || (this.eventList[event] = [])).push(fn);
                return this;
            },

            //取消关注
            unattention: function (event, fn) {
                // 获取该平台下面的所有关注者
                let fns = this.eventList[event];
                // 如果该平台下面没得关注者那么直接返回
                if (!fns) {
                    return false;
                }
                // 如果没有穿具体的关注者那么直接清除全部的关注者
                if (!fn) {
                    fns.splice(0, fns.length)
                }
                else {
                    fns.forEach(function (item, index) {
                        if (item === fn) {
                            //清除传递过来的关注者
                            fns.splice(index, 1);
                        }
                    })
                }
                return this;
            },

            //发布信息(开始直播)
            emitAction: function () {
                let event = Array.prototype.shift.call(arguments);
                let content = arguments[0];
                fns = this.eventList[event] || [];
                let _that = this;
                if (fns.length == 0) {
                    return false;
                }
                fns.forEach(function (fn) {
                    fn.call(_that, content)
                })
                return this;
            }

        }

        let C = function (content) {
            console.log("C男孩" + content)
        }

        let A = function (content) {
            console.log("A男孩" + content)
        }

        //订阅者一(C男孩)
        femaleAnchor.attention("douyu", C)

        //订阅者二(A男孩)
        femaleAnchor.attention("huya", A)

        //取消订阅者(A男孩)
        femaleAnchor.unattention("huya", A)

        //发布
        femaleAnchor.emitAction("douyu", "来斗鱼看直播了哦");
        femaleAnchor.emitAction("huya", "来虎牙看直播了哦");

3 区别

观察者模式

目标直接将通知分发到观察者身上

发布订阅者模式

目标首先是将通知分发到事件调度中心,事件调度中心再通过订阅者具体订阅的类型分发到不同的订阅者身上

总结

设计模式是在特定场景下面可以使用的解决方案,是前辈们在一些特殊的场景踩坑之后留下的解决问题的固定模式。有很多小伙伴会觉得学习涉及模式没有什么作用,业务代码中很少会涉及到,但是当大家业务代码写烦了去看vue或者react的源码的时候才会发现设计模式的重要性。