脑课堂编程教育

Javascript设计模式之"观察者模式"

包罗万象 4年前
74 0 0
脑课堂编程培训

一、什么是观察者模式?

观察者模式:它定义对象间一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖他的对象都将得到通知。

DOM事件的绑定,就是一个经典的发布-订阅模式

document.body.addEventListener('click', function () {
    alert(2)
}, false)

document.body.click() // 模拟用户的点击

在这里我们需要监听用户点击document.body的动作,但是我们无法知道用户什么时候点击,所以我们订阅document.body上的click事件,当body节点被点击时,body节点会向订阅者发布这个消息。

其实vuejs的双向数据绑定:也是利用观察者模式 + Object.defineProperty()对数据进行劫持来实现双向数据绑定的。后续有时间,可以写一篇文章来分析下!

二、观察者模式的好处是什么?

在我们了解到什么是观察者模式后,那么它在编程中有哪些好处呢?

1、用于异步编程回调,代替传统的回调函数的方案

2、可以取代对象之间硬编码的通知机制,代码解耦。 (如果有用vuejs做开的朋友可能会发现,Event Bus就是利用观察者模式来实现的)

// 比如,用户登录,通知其他模块更新
// 传统做法
login.success(function(data) {
    // 更新用户状态
    common.updateUserInfo()

    //刷新购物车
    cart.update()

    ...
})

// 采用观察者模式
$.ajax('http://xxx.com/login', function (data) {
    // 登录成功后,触发订阅事件
    subsEvent.tigger('loginSuccess', data)
})

// 各模块监听

var header = function () {
    subsEvent.listen('loginSuccess', function (data) {
        console.log('登录成功回调', data)
    })
}

var nav = function () {
    subsEvent.listen('loginSuccess', function (data) {
        console.log('登录成功回调', data)
    })
}

三、如何实现一个观察者模式呢?

聊了这么多,那么我们自己动手实现一个简单的观察者模式吧!

    var subsEvent = (function () {
            var clientList= [], // 缓存订阅者回调函数
                listen,
                tigger,
                remove;

            listen =  function (key, fn) {
                if (!clientList[key]) {
                    clientList[key] = []
                }
                clientList[key].push(fn) // 订阅消息添加到消息缓存列表
            }

            tigger = function () {
                var key = Array.prototype.shift.call(arguments), // 取出消息类型
                    fns = clientList[key] // 取出回调函数
                if (!fns || fns.length === 0) {
                    return false
                }
                for (var i =0; i < fns.length; i++) {
                    var fn = fns[i]
                    fn.apply(this, arguments)
                }
            }

            remove = function (key, fn) { // 删除订阅消息
                var fns = clientList[key]

                if (!fns) {
                    return false
                }

                if (!fn) { // 删除key所有的订阅
                    fns = []
                } else {
                    for (var i = 0; i < fns.length; i++) { // 删除对应的订阅事件
                        var _fn = fns[i]
                        if (_fn === fn) {
                            fns.splice(i, 1)
                        }
                    }
                }

            }
            return {
                listen: listen,
                tigger: tigger,
                remove: remove
            }
    })()

    // 订阅消息 
    subsEvent.listen('test1', fn1 = function (data) {
        console.log('触发 test1:', data)
    })

    subsEvent.listen('test2', fn2 = function (data) {
         console.log('触发 test2:', data)
    })

    // 触发订阅消息
    subsEvent.tigger('test1', '大家好,我是段亮,这是我写的一个观察者模式!')


    // 模拟异步场景调用
    setTimeout(() => {
       subsEvent.tigger('test2', '没关系, 继续加油!')

    }, 1000)

    // 删除订阅事件
    subsEvent.remove('test2', fn2)
收藏

本文标题:Javascript设计模式之"观察者模式"

本文链接:https://naoketang.com/p/wny7ne2k7ped

评论区

推荐课程