精华内容
下载资源
问答
  • 观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。 pubSub.png从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰。...

    之前一直对观察者模式和发布订阅模式的区别理解不深,正好这段时间在看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’事件的时候,作出一些处理。

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

    展开全文
  • 发布订阅模式,是javascript甚至大多数语言都有的语言模式,比较概念的解释是, 订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(第三方),由调度中心统一调度订阅者...
        

    概念

    发布订阅者模式,是javascript甚至大多数语言都有的语言模式,比较概念的解释是,

    订阅者把自己想订阅的事件注册到调度中心,当该事件触发时候,发布者发布该事件到调度中心(第三方),由调度中心统一调度订阅者注册到调度中心的处理代码。

    优缺点

    优点
    1.一对多。
    一个发布者可以绑定多个订阅者,当事件触发时,由调度中心全部通知。
    2.解耦。
    发布订阅者模式中,订阅者是不知道也不关心事件是为什么触发,是由哪一个事件触发,只知道事件触发时候,会告诉自己。发布者也不用一一通知,只要告诉调度中心,事件触发了就好了。所以代码松耦合。
    3.程序便于扩展。
    缺点:
    实现方式麻烦?

    举例

    用平时身边的例子解释,比如你被阿里邀请面试,面试完你问面试官什么时候出结果,面试官告诉你结果出来时候会通知你的,这样你就不用天天打电话问面试结果了,等面试结果出来,面试官会把面试结果统一发邮件给面试者,当你收到面试结果后,进行下一步操作,是到阿里上班,还是面试下一家。

    代码实现

    var observer = function () {
        var _observer = {};     
        let _queue = {};     // 所有事件的队列
        /**
        * @param 注册的事件名称
        * @param 事件触发时执行的函数
        */
        _observer.on = function (eventName, fn) {
            if (Object.prototype.toString.call(fn) !== '[object Function]') return;
            if (_queue[eventName] && _queue[eventName].length > 0) {
                // 如果之前注册过eventName事件
                _queue[eventName].push(fn);
            } else {
                // 之前没有注册过eventName事件
                _queue[eventName] = [fn];
            }
        },
         /**
        * @param 已经触发的事件(发布事件)
        */
        _observer.trigger = function (triggerEventName) {
            var args = Array.prototype.slice.call(arguments,1);
            if (!_queue[triggerEventName]) return;
            for (var i = 0; i < _queue[triggerEventName].length; i++) {
                _queue[triggerEventName][i].apply(null, args);
            }
        },
        // 移除注册事件
        _observer.remove = function (removeEventName) {
            for(var k in _queue) {
                if (k === removeEventName) {
                    delete _queue[k];
                }
            }
        }
        // 移除所有注册事件
        _observer.removeAll = function () {
            _queue = {};
        }
        return _observer;
    }()
    

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

    发布订阅者模式与观察者模式是很相似的,之前的好多网站、博客上也把它们画上等号,但是我前段时间接到一个面试,问我,发布订阅者模式与观察者模式有什么却别,当时说一样的,结果面试管说其实不一样,好吧,一脸懵逼,结束时候自己查阅了一下,确实不太一样。

    区别

    • 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过调度中心进行通信。
    • 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
    • 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)

    举个例子
    观察者模式就像你没有经验却买了比特币或者股票,然后害怕赔钱一直盯着k线图,一有变化立马就知道了,然后做下一步操作,是观望是买是抛都可以,熟悉vue的同学应该知道watch这个方法吧,对,就是观察者模式,国外有一图拿过来给你们看看
    图片描述

    参考

    1.观察者模式 vs 发布-订阅模式
    2.Observer vs Pub-Sub

    展开全文
  • 一,简介发布-订阅模式又叫做观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生...而发布/订阅模式中,发布者并不维护订阅者,也不知道订阅者的存在,所以也不会直接通知订阅者,而是通知调度...

    一,简介

    发布-订阅模式又叫做观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变的时候,所有依赖于它的对象都将得到通知。

    abb3f3feb48712f26ab52d531ed7e3f7.png

    两者最主要的区别在于是否有中间的调度中心。

    1. 观察者模式把订阅者维护在发布者这里,需要发布消息时直接发消息给订阅者。在观察者模式中,发布者本身是知道订阅者存在的。
    2. 而发布/订阅模式中,发布者并不维护订阅者,也不知道订阅者的存在,所以也不会直接通知订阅者,而是通知调度中心,由调度中心通知订阅者。
      由以上的描述可以看出,发布订阅模式是松散耦合的,而观察者模式强耦合。

    二,示例代码

    1,观察者模式

    观察者模式只有两个对象类,一个订阅者,一个发布者,在下面示例代码中,定义了SalesOffices 类为发布者,Observer为订阅者,发布者和订阅者都可以实例化多个,下面示例中实例化了一个发布者和两个订阅者,当发布者发布信息,订阅者就可以同步更新状态。

    class SalesOffices {
      constructor () {
        this.clientList = [];
      }
      add (callback) {
        this.clientList.push(callback);
      }
      notify () {
        this.clientList.forEach(callback => {
          callback.apply(this,arguments);
        });
      }
    }
    class Observer {
      constructor (salesOffices) {
        this.salesOffices = salesOffices;
        this.salesOffices.add(this.update);
      }
      update (price, squareMetar,) {
        console.log('价格:' + price + '万' + '面积:' + squareMetar);
      }
    }
    
    let salesOffices = new SalesOffices();
    let xiaoming = new Observer(salesOffices);
    let xiaohong = new Observer(salesOffices);
    // 发布给小明
    salesOffices.notify('200','88');
    // 发布给小红
    salesOffices.notify('100','100');
    
    // 运行结果:
    "价格:200万面积:88"
    "价格:200万面积:88"
    "价格:100万面积:100"
    "价格:100万面积:100"
    

    上面示例代码中的观察者模式存在的问题是,不管订阅者是谁,都无条件接受发布者发送的消息。下面一个示例会更具订阅者想要的信息进行发送!

    对比上面的代码,唯一的区别就是订阅者多添加了一个key值,传递给发布者,此时发布者就可以根据对应的key值对订阅者发布不同的消息,订阅者也只能接收到自己想要接收的消息

    class SalesOffices {
      constructor () {
        this.clientList = {};
      }
      
      add (key,callback) {
        if (!this.clientList[key]) {
           this.clientList[key] = [];
        }
        this.clientList[key].push(callback);
      }
      
      notify () {
        let key = Array.prototype.shift.call(arguments); //取出消息类型
        let fns = this.clientList[key]; 
        if (!fns || fns.length === 0) { // 如果没有订阅消息,则返回
            return false;
        }
         this.clientList[key].forEach(callback => {
             callback.apply(this,arguments);
         });
      }
    }
    
    class Observer {
       constructor (price,salesOffices) {
         this.price = price;
         this.salesOffices = salesOffices;
         this.salesOffices.add(this.price,this.update);
       }
      
       update (price, squareMetar) {
         console.log('价格:' + price + '万' + '面积:' + squareMetar);
       }
    }
    
    let salesOffices = new SalesOffices();
    let xiaoming = new Observer('squareMeter300',salesOffices);
    let xiaohong = new Observer('squareMeter200',salesOffices);
    
    // 发布给小明
    salesOffices.notify('squareMeter300','88','300');
    // 发布给小红
    salesOffices.notify('squareMeter200','100','200');
    
    // 结果
    "价格:88万面积:300"
    "价格:100万面积:200"
    

    2,发布订阅模式

    下面示例是就是为发布订阅模式,发布订阅模式,高度解耦,相比观察者模式,多了一层中介,这个中介不管订阅者和发布者关系,只是维护发送功能。

    class Publish {
      constructor () {
        this.pubArr = [];
      }
      
     addPub(office) {
       this.pubArr.push(office);
       return this;
     }
     
     pub (topic) {
       this.pubArr.forEach(item => {
          item.notify()
       })
       return this;
     } 
    }
    
    
    // 发布者
    class Office {
      constructor (price,squareMetar) {
        this.price = price;
        this.squareMetar = squareMetar
        this.OfficeArr = [];
      }
      
      addOffice(callback) {
         this.OfficeArr.push(callback);
      }
      
      notify () {
        this.OfficeArr.forEach(callback => {
             callback.apply(this,arguments);
        });
      }
    }
    
    // 订阅者
    class Observer {
       constructor (salesOffices) {
         this.salesOffices = salesOffices;
         this.salesOffices.addOffice(this.update);
         this.price = this.salesOffices.price;
         this.squareMetar = this.salesOffices.squareMetar;
       }
      
       update () {
         console.log('价格:' + this.price  + '万' + '面积:' + this.squareMetar);
       }
    }
    
    let publish = new Publish();
    let office1 = new Office(100,80);
    let office2 = new Office(200,90);
    let xiaoming = new Observer(office1);
    let xiaohong = new Observer(office2);
    
    publish.addPub(office1).addPub(office2);
    publish.pub(office1).pub(office2);
    

    三,总结

    以上就是观察者模式和发布订阅模式实现以及区别,平常开发中,推荐已观察者模式进行实现,发布订阅模式属于高度解耦,所以代码的整体可读性不高,不推荐使用

    展开全文
  • Github:... 场景是Assest/EventCetner.unity 相关代码详细的Test都在Github里,这里做个简单介绍 应用场景 1.... 2....EventCenter的功能是订阅发布模式调度中心,我称...

    Github:https://github.com/BellflowerRinging/UnityTest/Assest/src/EventCenter

    场景是 Assest/EventCetner.unity

    相关代码详细的Test都在Github里,这里做个简单介绍

    应用场景

      1.角色属性改变

      2.任务监听怪物死亡


    EventCenter的功能是订阅发布模式的调度中心,我称之为事件中心,是告知所有订阅者某个事件发生的模块。
    提供了相应的几个方法

        public void SetListener(SimpleEvent e)
        public void RemoveListener(SimpleEvent e)
        public void FireEvent(string t,string sender, IMessage m) // 事件类型,发送者,事件内容
    

    并非单例对象

    •   任何核心模块都可以new EventCenter()来管理这个核心模块下的事件调度


    SimpleEvent最简单的一个事件,是订阅者订阅的事件

    //构造函数
    public SimpleEvent(string e,string sender, UnityAction<IMessage> action)  //事件类型,发送者,事件发生后要执行的委托

     

    例子:PlayerA的生命值改变(EventType.HpChange)更新生命条(HpBar)

    HpBar控制类初始化的时候 

    SimpleEvent e = new SimpleEvent(EventType.HpChange,"PlayerA",(message)=>{ UpdateHpBar(message); });
    Player.EventCenter.SetListener(e);

    PlayerA控制类的SetHp方法里

    Player.EventCenter.FireEvent(EventType.HpChange, "PlayerA", IMessage);

    FireEvent的时候事件中心对所有的订阅者进行遍历当EventType和Sender都符合的时候,调用

    SimpleEvent.UnityAction<IMessage>委托,并传递message

    至此完成一次事件的调度对HpBar和PlayerA进行了双向的解耦

     

    简单看一下使用例子,详细实现代码都在Github里

    监听

            // 1.角色属性改变
            SimpleEvent prop_change = new SimpleEvent(ActorEventType.PROR_CHANGE, "PlayerA", (message) =>
            {
                var mes = message.ConvertTo<ActorChangeMessage>(false);
                Debug.Log(string.Format("响应事件输出内容 属性:{0},改变前:{1},改变后:{2}", mes.PropName, mes.CurValue, mes.ChangeValue));
            });
    
            m_game.EventCenter.SetListener(prop_change);
    
            // 2.怪物死亡 发送者可谓null 这就意味着任何怪物死亡都会被监听
            SimpleEvent monster_meath = new SimpleEvent(MonsterEventType.DEATH, null, (message) =>
            {
                var mes = message.ConvertTo<MonsterDeathMessage>(false);
                Debug.Log(string.Format("响应事件输出内容 怪物:{0},击杀者:{1}", mes.Monster.ToString(), mes.Killer.ToString()));
    
                // if(mes.Monster == monster && player==self) do..
            });
    
            m_game.EventCenter.SetListener(monster_meath);

    发送

    
            ActorChangeMessage mes = new ActorChangeMessage("Hp", "100", "50");
            m_game.EventCenter.FireEvent(ActorEventType.PROR_CHANGE, "PlayerA", mes);
    
            MonsterDeathMessage mes1 = new MonsterDeathMessage("MonsterA", "PlayerA");
            m_game.EventCenter.FireEvent(MonsterEventType.DEATH, null, mes1);

    这个模块相当于盲写 还没仔细测过

    还有很多细节没有写出来 有空再来完善

    下篇笔记讲讲MonoEvent 或者 IMessage

    展开全文
  • 观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心。 pubSub.png 从图中可以看出,观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不...
  • 发布订阅模式简介:订阅者(Subsciber)通过事件注册(Subscribe)将订阅事件提交到调度中心(Topic),调度中心保存好订阅者的注册信息(回调函数),每当发布者(Publisher)发布事件的时候,通过事件发布(Publish...
  • 最近看到很多文章分析发布订阅模式和观察者模式的异同,其实在大多关于设计模式的书籍里面都认为二者是一样的。 发布订阅模式,又叫做观察者模式,又叫做消息机制,它定义对象间的一种一对多的依赖关系,当一个对象...
  • 最简的发布订阅模式

    2019-10-01 21:32:18
    发布订阅模式 1. 个人仅以最简单的发布订阅模式呈现该模式的思想,主要注重该思想的理解,同于多处理异步,切片事件等操作 发布订阅的理解(个人) 1.主要原理是依次去获取调度中心的状态,整个数据是在调度中心...
  • 题意描述: 观察者模式和发布订阅模式有什么不同 ? 手写一个观察者模式的例子 ? 解题思路: Alice: 上次讲了观察者模式,...而在发布订阅模式中,发布者和订阅者之间多了一个调度中心。调度中心一方面从发布者...
  • 发布订阅模式与观察者模式的区别在于,观察者模式是松耦合,而发布者与订阅者是解耦的,它们彼此互不认识,发布者需要告诉调度中心要发的消息是什么,订阅者需要向调度中心订阅事件,当发布者发布此类事件时,也就是...
  • 在结构上,观察者模式只有对象和观察者,发布订阅模式中存在 发布者、订阅者以及中间的调度中心。 使用意图 发布订阅者模式可以为对象创建一对多的关系,并在发布者发生改变时通知其订阅者。 使用场景 发布订阅者...
  • 发布订阅模式发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。 那他们之间如何交流? 由一个调度中心来做中间人,发布者更新(publish)主题,由主题(调度中心)来进行通知...
  • 概念 观察者模式 定义对象间一种一对多的依赖关系,使得每当一个对象改变...发布订阅模式里有三种角色:发布者、订阅者、调度器(第三者)。 往更深层次讲: 观察者和被观察者是松耦合的关系。 发布者和订阅者则
  • 发布订阅模式(Js)

    2020-11-07 00:58:31
    一、什么是发布订阅模式发布订阅模式中,可以有多个订阅者,但却只能有一个发布者。当发布者发布某一新消息时,所有的订阅者都可以接收到该消息。 具体实现过程可大致分为: 订阅者先在事件调度中心里注册事件...
  • 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心,如下图结构。 1、在实际开发中,经常会遇到某个方法内处理很多的逻辑,最简单的就是直接在方法内直接写。这种是高度耦合的面向过程的写法。对于代码...
  • 概念 首先说明一下,发布-订阅模式并不等同于观察者模式,这两者是有区别的。举例说明,用户直接向出版社订阅杂志,出版社直接把杂志发送给订阅杂志的用户,这种场景...上图发布订阅模式进行抽象如下图,借图一用:
  • 发布、订阅,从名称上能够联想到文章的发布和订阅。比如公众号运营者在公众...发布订阅模式和观察者模式非常相像,很多人认为这两种模式是一样的,如果不考虑调度中心,这两种模式没啥差别,如果把调度中心考虑进去...
  • 发布订阅模式是发布者不直接将消息发送给接收者(订阅者),而是将消息发给一个调度中心,调度中心根据消息的不同类别,向订阅者广播下去。 举例 拿微信公众号举例,有很多个用户关注分别关注A、B、C等公众号,一个...
  • // 发布订阅 // 创建一个对象 // 在该对象上创建一个缓存列表(调度中心) // on 方法用来把函数 fn 都加到缓存列表中(订阅者注册事件到调度中心) // emit 方法取到 arguments 里第一个当做 event,根据 event...
  • this.eventList = {} //事件调度中心 } on(type,func){//订阅 if(!this.eventList[type]){ this.eventList[type] = [] } this.eventList[type].push(func) } emit(type,val){//发布 if(!this....
  • 观察者订阅目标事件,目标发生变化后,调度观察者的更新方法。 ╭─────────────╮ Fire Event ╭──────────────╮ │ │─────────────&gt;│ │ │ Subject │ │ ...
  • 观察者模式和发布订阅模式最大的区别就是发布订阅模式有个事件调度中心 发布订阅模式 发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰 class E { constructor(){ this.event = [] } on(event...
  • 最近被人问到设计模式,观察者(Observer)模式发布(Publish)/订阅(Subscribe)模式二者有什么区别。其实这两种模式还是有些许差异的,本质上的区别是调度的方式不同。 观察者模式 观察者模式,目标和观察者是...
  • 虽然两种模式都存在订阅者和发布者(具体观察者可认为是订阅者、具体目标可认为是发布者,取消订阅也可以看作是取消观察者),但是观察者模式是由具体目标调度的,而发布/订阅模式是统一由调度中心调的,所以观察者...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 140
精华内容 56
关键字:

发布订阅模式调度