精华内容
下载资源
问答
  • 观察者模式是观察者被观察者之间通信,而发布订阅模式中间增加了一个中转层,通过第三方来分发信息。 观察者模式 // Subject为被观察者,Subject中状态(state)改变,就通知 Observer更新 class ...

    有些人认为观察者模式就是发布订阅模式,实际上观察者模式是包含了订阅发布模式,发布订阅模式只是观察者模式中的一种。观察者模式是观察者和被观察者之间的通信,而发布订阅模式中间增加了一个中转层,通过第三方来分发信息。

     

    观察者模式

        // Subject为被观察者,Subject中的状态(state)改变,就通知 Observer更新
        class Subject {
          constructor() {
            this.observes = []
            this.state = false
          }
          // this.observes存储观察者
          attach(observe){
            this.observes.push(observe)
          }
          // 状态改变,通知 Observer 触发更新
          setState(newState){
            this.state = newState
            this.observes.forEach( observer => observer.update(newState))
          }
        }
        // Observer为观察者,观察Subject的状态是否改变
        class Observer {
          constructor(name) {
            this.name = name
          }
          // 更新
          update(state){
            console.log(this.name + ",接收到了通知,被观察者的属性变为 " + state)
          }
        }
        var sub = new Subject()
        var obs1 = new Observer('观察者1')
        var obs2 = new Observer('观察者2')
        sub.attach(obs1)
        sub.attach(obs2)
        // 被观察者的状态改变,触发观察者更新
        sub.setState(true) 

    vue数据劫持中就用到了观察者模式,data中的属性一发生变化,就通知view界面更新,从而实现数据驱动,想要进一步了解vue底层原理,可以参考可以参考github上的一篇文章  MVVM实现

     

    发布订阅模式

     // 发布订阅
        class Events {
          constructor() {
            this.sub = {} // 容器
          }
          // 根绝不同 name,订阅对应函数
          $on(name, fn) {
            const wrap = this.sub[name] || (this.sub[name] = [])
            wrap.push(fn)
          }
          // 遍历所有相同name的订阅函数,并发布
          $emit(name, ...args) {
            const fns = this.sub[name] || []
            fns.forEach(fn => {
              fn.apply(this, args)
            })
          }
          // 销毁,避免内存泄漏
          $of(name){
            this.sub[name] = null
          }
        }
        // event 相当于中转器
        const event = new Events()
        // 订阅
        event.$on('eventname', function (a, b) {
          console.log(a, b)
        })
        event.$on('eventname', function (a, b) {
          console.log(a, b)
        })
        // 发布
        event.$emit('eventname', 'a', 'b')

    vue中的兄弟组件通信bus的原理就是发布订阅模式,该模式有个缺点,当你订阅一个消息后,也许此消息最后都未发生,但这个订阅者会始终存在于内存中。所以该消息不使用的时候,调用$of销毁,以避免内存泄漏。

     

    总结

    总而言之,在观察者模式中,观察者(Observer)是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布订阅通过共享全局状态,往往更多执行异步事件~~~~。

    展开全文
  • 观察者模式 观察者模式定义了对象间一种一对多依赖关系,当一个对象状态发生改变时,所有依赖于它对象都将得到通知,并自动...三 观察者模式发布订阅模式区别观察者模式发布订阅模式优缺点 ...

    一 观察者模式

    观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新。观察者模式属于行为型模式,行为型模式关注的是对象之间的通讯,观察者模式就是观察者和被观察者之间的通讯。

    简单实现就是被观察者里面存储了观察者的对象列表,当被观察者发生某种行为时,会回调观察者的方法。抽象代码如下:

    public abstract class Subject {
        private List<Observer> observers=new ArrayList<Observer>();//用于保存已订阅的目标的观察者
        public void attach(Observer observer){//订阅目标对象
            observers.add(observer);
        }
        public void detach(Observer observer){//解除订阅关系
            observers.remove(observer);
        }
        protected void notifyObserver(){//通知已订阅的观察者
            for (Observer observer : observers) {
                observer.updata(this);
            }
        }
    }
    

    二 发布订阅模式

    在软件架构中,发布-订阅是一种消息范式,消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者(如果有的话)可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者(如果有的话)存在。

    在这里插入图片描述
    完成订阅发布整个流程需要三个角色:

    • 发布者
    • 事件中心
    • 订阅者

    三 观察者模式与发布订阅模式区别

    先一张图看看这两者的区别:
    在这里插入图片描述

    可以看出,发布订阅模式相比观察者模式多了个事件通道,事件通道作为调度中心,管理事件的订阅和发布工作,彻底隔绝了订阅者和发布者的依赖关系。即订阅者在订阅事件的时候,只关注事件本身,而不关心谁会发布这个事件;发布者在发布事件的时候,只关注事件本身,而不关心谁订阅了这个事件。

    观察者模式有两个重要的角色,即目标和观察者。在目标和观察者之间是没有事件通道的。一方面,观察者要想订阅目标事件,由于没有事件通道,因此必须将自己添加到目标(Subject)
    中进行管理;另一方面,目标在触发事件的时候,也无法将通知操作(notify) 委托给事件通道,因此只能亲自去通知所有的观察者。

    差异总结:

    • 角色角度来看,订阅发布模式需要三种角色,发布者、事件中心和订阅者。二观察者模式需要两种角色,目标和观察者,无事件中心负责通信。
    • 从耦合度上来看,订阅发布模式是一个事件中心调度模式,订阅者和发布者是没有直接关联的,通过事件中心进行关联,两者是解耦的。而观察者模式中目标和观察者是直接关联的,耦合在一起(有些观念说观察者是解耦,解耦的是业务代码,不是目标和观察者本身)。

    四 观察者模式与发布订阅模式优缺点

    订阅发布模式优点
    灵活
    由于订阅发布模式的发布者和订阅者是解耦的,只要引入订阅发布模式的事件中心,无论在何处都可以发布订阅。同时订阅发布者相互之间不影响。

    订阅发布模式在使用不当的情况下,容易造成数据流混乱,所以才有了 React 提出的单项数据流思想,就是为了解决数据流混乱的问题。

    订阅发布模式缺点
    容易导致代码不好维护
    灵活是有点,同时也是缺点,使用不当就会造成数据流混乱,导致代码不好维护。

    性能消耗更大
    订阅发布模式需要维护事件列队,订阅的事件越多,内存消耗越大。

    观察者模式优点
    响应式
    目标变化就会通知观察者,这是观察者最大的有点,也是因为这个优点,观察者模式在前端才会这么出名。

    观察者模式缺点
    不灵活
    相比订阅发布模式,由于目标和观察者是耦合在一起的,所以观察者模式需要同时引入目标和观察者才能达到响应式的效果。而订阅发布模式只需要引入事件中心,订阅者和发布者可以不再一处。

    参考:
    https://segmentfault.com/a/1190000020169229
    https://www.cnblogs.com/onepixel/p/10806891.html

    展开全文
  • 之前一直对观察者模式和发布订阅模式的区别理解不深,正好这段时间在看vue源码的分析,vue数据双向绑定也用到了发布订阅模式,于是又把这两者探究了一番,今天做个笔记加强印象。观察者模式和发布订阅模式最大的区别...

    之前一直对观察者模式和发布订阅模式的区别理解不深,正好这段时间在看vue源码的分析,vue数据双向绑定也用到了发布订阅模式,于是又把这两者探究了一番,今天做个笔记加强印象。

    观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。

    24419e1a1d60d258fe110f757f7fb788.png

    pubSub.png

    从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。这样一方面实现了解耦,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的。还可以做一些节流操作。

    接下来看一下代码实现

    观察者模式:

    // 观察者

    class Observer {

    constructor() {

    }

    update(val) {

    }

    }

    // 观察者列表

    class ObserverList {

    constructor() {

    this.observerList = []

    }

    add(observer) {

    return this.observerList.push(observer);

    }

    remove(observer) {

    this.observerList = this.observerList.filter(ob => ob !== observer);

    }

    count() {

    return this.observerList.length;

    }

    get(index) {

    return this.observerList(index);

    }

    }

    // 目标

    class Subject {

    constructor() {

    this.observers = new ObserverList();

    }

    addObserver(observer) {

    this.observers.add(observer);

    }

    removeObserver(observer) {

    this.observers.remove(observer);

    }

    notify(...args) {

    let obCount = this.observers.count();

    for (let index = 0; index < obCount; index++) {

    this.observers.get(i).update(...args);

    }

    }

    }

    发布订阅模式:

    class PubSub {

    constructor() {

    this.subscribers = {}

    }

    subscribe(type, fn) {

    if (Object.prototype.hasOwnProperty.call(this.subscribers, type)) {

    this.subscribers[type] = [];

    }

    this.subscribers[type].push(fn);

    }

    unsubscribe(type, fn) {

    let listeners = this.subscribers[type];

    if (!listeners || !listeners.length) return;

    this.subscribers[type] = listeners.filter(v => v !== fn);

    }

    publish(type, ...args) {

    let listeners = this.subscribers[type];

    if (!listeners || !listeners.length) return;

    listeners.forEach(fn => fn(...args));

    }

    }

    let ob = new PubSub();

    ob.subscribe('add', (val) => console.log(val));

    ob.publish('add', 1);

    从上面代码可以看出,观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,会造成代码的冗余。而发布订阅模式则统一由调度中心处理,消除了发布者和订阅者之间的依赖。

    观察者模式跟我们平时用的事件也有一定的关系,比如:

    ele.addEventListener('click', () => {});

    addEventListener就相当于注册了一个观察者,当观察到‘click’事件的时候,作出一些处理。

    好啦,内容基本就这些,如果有什么不对的地方,欢迎指正哦~

    展开全文
  • 观察者模式和发布者-订阅者模式的区别 观察者模式 观察者模式是设计模式中的一种行为型模式,观察者模式是前端设计模式的核心。 观察者模式定义了一种一对多的对象依赖关系,当被依赖的对象的状态发生了改变,所有...

    观察者模式和发布者-订阅者模式的区别

    观察者模式

    观察者模式是设计模式中的一种行为型模式,观察者模式是前端设计模式的核心。

    观察者模式定义了一种一对多的对象依赖关系,当被依赖的对象的状态发生了改变,所有依赖它的对象都会得到通知。

    观察者模式的目的是为了改善传统的通知机制,解耦通知方和被通知方的关系。

    在这里插入图片描述

    • Observer 是观察者,它有一个update方法,当观察者需要被触发的时候执行update。
      • 观察者定义好以后,它就等待被更新,等待被触发,当然,前提是它已经定义好了。
    • Subject 是主题,主题可以绑定多个观察者,放在observers里面。一对多的依赖关系。
      • 主题可以获取状态:getState()
      • 主题可以设置状态:setState(),当状态设置完成后,会触发所有的观察者:notifyAllObservers(),触发所有观察者里面的update方法。
      • 一对多,主题是一个,观察者可能是多个。

    观察者模式的简单实现

    class Observer {
        constructor(label) {
            this.label = label
        }
        update() {
            console.log(`update${this.label}`)
        }
    }
    
    class Target {
        constructor() {
            this.observerList = []
        }
        add(observer) {
            this.observerList.push(observer)
        }
        remove(observer) {
            this.observerList = this.observerList.filter(ob => ob !== observer)
        }
        notify() {
            this.observerList.forEach(ob => {
                ob.update()
            })
        }
    }
    
    let tar = new Target()
    for (let i = 0; i < 10; i++) {
        tar.add(new Observer(i))
    }
    tar.notify() 
    

    打印结果

    在这里插入图片描述

    发布者-订阅者模式

    发布者-订阅者模式在观察者模式的基础上,在发布者和观察者之间增加一个调度中心
    订阅者(观察者)把订阅的事件注册到调度中心,当该事件触发时候,发布者(目标)发布该事件到调度中心,由调度中心统一调度订阅者注册到调度中心的处理代码。

    发布者-订阅者模式的简单实现

    class Publisher {
        constructor() {
            this.subscribers = {}
            this.cache = {}
        }
    
        add(type, fn) {
            if (Object.prototype.toString.call(fn) !== '[object Function]') return
            this.subscribers[type] ? this.subscribers[type].push(fn) : this.subscribers[type] = [fn]
            return this
        }
    
        publish(type, theme) {
            //存储主题信息
            this.cache[type] ? this.cache[type].push(theme) : this.cache[type] = [theme]
            let subscribers = this.subscribers[type]
            if (!subscribers || !subscribers.length) {
                console.warn('no subscriber in subscribers.')
                return this
            }
            subscribers.forEach(fn => fn.call(this, theme))
            return this
        }
    
        unbind(type, fn) {
            this.subscribers[type] = this.subscribers[type].filter(item => item !== fn)
            return this
        }
    
        history(type, fn) {
            let cache = this.cache[type] || []
            cache.forEach(item => fn.call(this, item))
            return this
        }
    }
    
    let sub1 = data => {
        console.log(`sub1${data}`)
    }
    let sub2 = data => {
        console.log(`sub2${data}`)
    }
    let sub3 = data => {
        console.log(`sub3${data}`)
    }
    let publisher = new Publisher()
    
    publisher.add('click', sub1).add('click', sub2).add('change', sub3)
    
    publisher.publish('click', '第一次click').publish('change', '第一次change')
    
    publisher.unbind('click', sub1).publish('click', '第二次点击').history('click', data => {
        console.log('history' + data)
    })
    

    如以上代码,发布者订阅者模式可以在调度中心(相当于代码中的publish函数)进行一些定制化的操作,比如进行节流操作,过滤操作,权限控制等等,个人感觉会比较灵活一点。

    打印结果

    在这里插入图片描述

    观察者模式和发布者-订阅者模式的区别

    相同点

    两者的目的都是为了改善传统的通知机制,解耦通知方和被通知方的关系。

    区别

    发布者-订阅者模式相对于观察者模式而言,多了一个类似于调度中心的存在,发布者-订阅者模式能集中管理多个主题对象,并且观察者和发布者之间是不存在直接关系的,在调度中心可以很方便的实现分发管理,这个特性让发布者-订阅者模式变得更加灵活。

    在这里插入图片描述
    观察者模式是由具体目标调度的,而发布者-订阅者模式是统一由调度中心调度的,所以观察者模式的观察者与发布者之间是存在依赖的,而发布者-订阅者模式则不会。所以发布者-订阅者模式的组件是松散耦合的。

    展开全文
  • 观察者模式和发布订阅模式的区别 谈谈观察者模式和发布订阅模式 设计模式(三):观察者模式与发布/订阅模式区别 转载于:https://www.cnblogs.com/ziyoublog/p/10954943.html...
  • 观察者模式和发布订阅模式区别观察者模式和发布订阅模式区别:一、从表面上看:二、往更深层次讲:三、从使用层面上讲:四、总结: 观察者模式和发布订阅模式区别: 一、从表面上看: 观察者模式里,只有两个角色 ...
  • 观察者和发布订阅模式的区别 观察者模式和发布订阅模式有什么区别? 大多数的回答都是:Publishers + Subscribers = Observer Pattern,24种基本的设计模式并没有发布-订阅模式,发布订阅模式属于并发型模式;像典型...
  • 观察者模式: 订阅发布模式: ...2.可以把restful请求的通信方式,看做观察者模式的应用;而服务总线(MQ)的方式,则是订阅发布模式 转载于:https://www.cnblogs.com/xujanus/p/9004753.ht...
  • 发布订阅模式和观察者模式也是面试当中被经常提及的考察点。读过vue源码的都知道vue的底层视图更新也用到了观察者模式。下面我就直接把源码写出来,注释相当详细,不再赘述。 1.发布订阅模式 /* 发布订阅模式的...
  • 观察者模式和发布订阅模式的区别观察者模式的Subject就向一个发布者Publisher,观察者(Observer)订阅者(Subscriber)关联。subject通知observers就像publisher发布一样。发布订阅模式从广义上来讲就是观察...
  • 观察者模式 VS 发布订阅模式,面试官问我观察者模式和发布订阅模式的区别
  • 发布订阅模式和观察者模式有以下不同: 观察者模式中,观察者和主题都知道对方存在;而在发布订阅模式中,生产者与消费者不知道对方存在,它们之间通过频道进行通信。 观察者模式是同步,当事件触发时...
  • 观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,订阅和订阅目标是联系在一起,当订阅目标发生改变时,逐个通知订阅者。 【2】案例 案例:我办了一个补习班,学生想来我这学习,必须先...
  • 什么是发布订阅?这里实现一个简单的发布订阅说明一下。 myEvent = { arr:[], on(fn){ this.arr.push(fn); }, emit(){ this.arr.forEach(item=>item()) } } myEvent.on(()=&g...
  • 1.发布订阅模式是最常用的一种观察者模式的实现,并且从解耦重用角度来看,更优于典型的观察者模式 2. 订阅者有调度中心 观察者模式: 发布订阅模式: 代码实现上的区别: //观察任意数组...

空空如也

空空如也

1 2 3 4 5 ... 11
收藏数 202
精华内容 80
关键字:

发布订阅和观察者模式的区别