从 javaScript 看观察者模式

「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战」。

前言

相信很多人都会听过观察者模式,因为 vue 的知名度摆在这,哪怕是前端入门的程序员,只要知道 vue 都可能听说过观察者模式。vue 自身也是观察者模式的实践例子。

观察者模式是什么

观察者模式是一种设计模式,他可以根据统一接口 depend, notify 进行解耦(当然名字叫什么都行)。在观察者模式里有两个角色,一个是关注者,一个是被关注者。两者之间相互交流,其他人没有办法插足。关注者进行了 depend 关注这个动作之后,被关注者会将关注者存起来。被关注者可以通知他的关注者,至于执行什么内容,由关注者决定,被关注者只是发出通知。至于被关注者什么时候通知,关注者并不了解,只知道收到通知之后做什么。

特点

  1. 容易维护。

由于只有两个角色,并且角色之间的分工明确,所以编写代码的时候如果需要添加功能或者修改功能,可以明确的知道该修改什么地方。

  1. 不够灵活。

虽然是一体两面,这个特点看上去和第一个特点相反。假设一个场景,当系统的交互比较复杂,而且庞大的时候,所关注的变量可能在各个地方都有引用,这时候注册的关注者是数量非常大的,但是我们需要每个地方都马上根据通知整改吗?实际上往往不需要,比如跳了另一个路由,页面正在展示另一个组件,当收到通知的时候,前一个路由其实是不需要马上修改的。可以等到路由再次展示的时候才修改。并且由于关注者是按照代码执行顺序收集的,所以在通知的时候,反而是更靠前的路由先收到通知。所以需要做其他的额外的处理对观察者模式进行优化。

什么时候用

  1. 全局状态

全局状态就不用多解释了,就是里面的值在多个地方被使用,而且他们是同一个值。需要实现真正的一呼百应。这时候观察者模式可以发挥巨大作用。但是要主要上面所说可能出现的问题。但是其实全局状态范围不一定非得是很大的范围。比如 vue 里面每个实例的数据,都只限于在这个实例的范围,也就是这个组件的范围,那么当这个组件被销毁后或者跳到另一个组件的时候,就不会出现关注过多的情况。

  1. 在改变一个值需要做很多操作的时候

当有这样一个需求,我们站起来后要先左手要先抬起来,右脚往前迈一步,然后身体左转,右手再捂住嘴巴。我们有一个触发的扳机,并且后面跟着很多操作。那么我们就可以关注站起来,然后左手右脚身体右手去注册自己一会要做的事情。这时候,只要我们一调用站起来,其余的动作就会自己完成。

如果没有观察者模式会怎么办。我们可能会写一个函数,设置一套动作,这个是属于另外一种设计模式了。

    function action() {
        站起来()
        举左手()
        跨右脚()
        左转()
        举右手()
    }
复制代码

如何用 JavaScript 实现观察者模式

    // 被关注者
    class Observer {
        constructor() {
            this.deps = []
        }
        
        depend(dep) {
            this.deps.push(dep)
        }
        
        notify() {
            this.deps.forEach(dep => dep.notify())
        }
        
        removeNotify(dep) {
            const i = this.deps.indexOf(dep)
            if (i > -1) {
                this.deps.splice(i, 1)
            }
        }
    }
    
    // 关注者
    class Watcher {
        constructor(action) {
            this.action = action
        }
        
        depend(observer) {
            this.observer = observer
            observer.depend(this)
        }
        
        removeDepend() {
            if (this.observer) {
                this.observer.removeNotify(this)
            }
        }
        
        notify() {
            // 默认操作和自定义操作
            this.action()
        }
    }
复制代码

以上就是观察者模式的一些心得,以后会介绍更多的模式,第一次总结难免有缺陷,但是可以一直迭代,喜欢可以关注这个专栏。

猜你喜欢

转载自juejin.im/post/7067912063615500318