Observer观察者模式

Observer观察者模式和Pub/sub模式事实上都是同一套路。这种模式建立起了不同对象之间的依赖关系:

图片描述

当一个对象触发某个方法,或者发生变化时,其他关注这个对象的对象们,也会响应这个对象的变化。

    function setObserverBehavior (subjects) {
        if (!Array.isArray(subjects)) {
            if (subjects.length) {
                subjects = Array.from(subjects)
            } else {
                subjects = [subjects]
            }
        }
        
        subjects.forEach(function (subject) {
            subject.watchBy = function (target, type) {
                subject.addEventListener(type, function (evt) {
                    evt.sender = subject
                    evt.recevier = target
                    target.notice && target.notice(evt)
                })
            }
        })
    }
    
    setObserverBehavior(observer)
    // 定义subjectOne对observer的依赖
    observer.watchBy(subjectOne, 'scroll')
    // 定义subjectTwo对observer的依赖
    observer.watchBy(subjectTwo, 'scroll')
    
    // 当observer触发scroll事件的时候,subjectOne会响应这个事件
    subjectOne.notice = function (evt) {
        const { sender, receiver } = evt
        // do something
    }
    
    // 当observer触发scroll事件的时候,subjectTwo会响应这个事件
    subjectTwo.notice = function (evt) {
        const { sender, receiver } = evt
        // do something
    }

显然,在需要建立依赖关系不多的几个对象中,使用Observer模式可以很好的将不同对象之间进行解耦:定义一个被观察者的主体,然后添加观察者对被观察者的依赖关系。但是需要建立依赖关系的对象一旦多起来,那么大家也可以想象下,自己手动去维护这些依赖关系是多么的蛋疼。

Mediator中介者模式

图片描述

基本的套路就是:提供一个中介对象Mediator,这个中介对象就是其他所有对象之间的联系纽带,其他所有对象相互之间没有没有任何的依赖关系,事件的订阅及发布统一让Mediator去操作。其他所有的对象需要做的就是提供给Mediator需要发布的事件,以及订阅Mediator上能提供的事件。

举个例子:

淘宝商铺:卖家A淘宝上开了一个Gopro相机店,b, c, d最近都有意愿去买Gopro,但是觉得价格稍贵,因此暂时不打算入手,想等价格稍微便宜一点后再入手,所以这3个人通过淘宝先关注卖家A的相机店。等到卖家AGopro相机打折后,淘宝会向这3个人推送打折消息。

其中这3个买家之间是没有任何依赖关系的,并不知道对方。当一个买家不打算买这家店的相机,取消关注后,对其他2个买家没有任何影响,唯一不同的是,卖家AGopro相机打折后,淘宝只会通知仍然关注卖家A的2个买家

在这个例子当中:

  • 淘宝: Mediator

  • 卖家A: 发布者

  • 买家B/C/D: 订阅者

发布者通过Mediator去发布消息,Mediator再去通知其他的订阅者

简单的实现:

    class Mediator {
        constructor () {
            this.subscribers = {}
        }
        
        pubNotice (type, obj) {
            this.subscribers[type] = this.subscribers[type] || []
            this.subscribers[type].forEach(sub => {
                sub(obj)
            })
        }
        
        subNotice (type, target, fn) {
            this.subscribers[type] = this.subscribers[type] || []
            this.subscribers[type].push(fn)
        }
    }
    
    const sub1 = {
        sayHi(data) {
        console.log(`sub1 get the data ${data}`)
        }
    }

    const sub2 = {
        sayHi(data) {
            console.log(`sub2 get the data ${data}`)
        } 
    }

    const mediator = new Mediator()

    mediator.subNotice('sayHi', sub1, sub1.sayHi)
    mediator.subNotice('sayHi', sub2, sub2.sayHi)

    mediator.removeNotice('sayHi', sub2, sub2.sayHi)

    mediator.pubNotice('sayHi', '你好')

ObserverMediator实现的套路上来看,二者都有相似之处,就是订阅者订阅发布者发布的消息,但是Observer订阅者发布者直接产生依赖关系,当依赖关系变多起来就不好处理了。而Mediator是在订阅者发布者中间加了一个中介者,由这个中介者去管理不同对象之间的订阅发布关系,这样的好处就是订阅者发布者不产生直接的依赖关系,统一交给中介者去维护。


苹果小萝卜
5.1k 声望356 粉丝

Github: [链接]