精华内容
下载资源
问答
  • 主要介绍了Vue发布订阅模式实现过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 主要介绍了JavaScript设计模式之观察者模式(发布订阅模式)原理与实现方法,结合实例形式分析了JavaScript观察者模式概念、原理、使用方法及相关操作注意事项,需要的朋友可以参考下
  • js代码-发布订阅模式 JavaScript 发布-订阅模式 - 掘金 https://juejin.im/post/6844903850105634824
  • 比如addEventListener 这个api就是个发布订阅模式 如果用过vue的同学,可以把他类比于 watch 下面我们看一个例子 var observe={ fnsObj:{}, // 订阅方法 on:function(key,fn){ if(!observe.fnsObj[key]){ ...
  • 发布订阅模式

    千次阅读 2020-10-13 16:08:08
    简单的买鞋订阅例子 var shoeObj = {}; shoeObj.list = []; shoeObj.listen = function (key, fn) { if (!this.list[key]) { this.list[key] = []; } this.list[key].push(fn) } shoeObj.notify = function ()...

    发布订阅模式介绍

    发布—订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。

    现实生活中的发布-订阅模式;

    比如小红最近在淘宝网上看上一双鞋子,但是呢 联系到卖家后,才发现这双鞋卖光了,但是小红对这双鞋又非常喜欢,所以呢联系卖家,问卖家什么时候有货,卖家告诉她,要等一个星期后才有货,卖家告诉小红,要是你喜欢的话,你可以收藏我们的店铺,等有货的时候再通知你,所以小红收藏了此店铺,但与此同时,小明,小花等也喜欢这双鞋,也收藏了该店铺;等来货的时候就依次会通知他们;

    在上面的故事中,可以看出是一个典型的发布订阅模式,卖家是属于发布者,小红,小明等属于订阅者,订阅该店铺,卖家作为发布者,当鞋子到了的时候,会依次通知小明,小红等,依次使用旺旺等工具给他们发布消息;

    发布订阅模式的优点:

    • 支持简单的广播通信,当对象状态发生改变时,会自动通知已经订阅过的对象。
      比如上面的列子,小明,小红不需要天天逛淘宝网看鞋子到了没有,在合适的时间点,发布者(卖家)来货了的时候,会通知该订阅者(小红,小明等人)。

    • 发布者与订阅者耦合性降低,发布者只管发布一条消息出去,它不关心这条消息如何被订阅者使用,同时,订阅者只监听发布者的事件名,只要发布者的事件名不变,它不管发布者如何改变;同理卖家(发布者)它只需要将鞋子来货的这件事告诉订阅者(买家),他不管买家到底买还是不买,还是买其他卖家的。只要鞋子到货了就通知订阅者即可。

      对于第一点,我们日常工作中也经常使用到,比如我们的ajax请求,请求有成功(success)和失败(error)的回调函数,我们可以订阅ajax的success和error事件。我们并不关心对象在异步运行的状态,我们只关心success的时候或者error的时候我们要做点我们自己的事情就可以了~

    发布订阅模式的缺点:

    • 创建订阅者需要消耗一定的时间和内存。
    • 虽然可以弱化对象之间的联系,如果过度使用的话,反而使代码不好理解及代码不好维护等等。

    如何实现发布–订阅模式?

    首先要想好谁是发布者(比如上面的卖家)。

    然后给发布者添加一个缓存列表,用于存放回调函数来通知订阅者(比如上面的买家收藏了卖家的店铺,卖家通过收藏了该店铺的一个列表名单)。

    最后就是发布消息,发布者遍历这个缓存列表,依次触发里面存放的订阅者回调函数。

    我们还可以在回调函数里面添加一点参数,比如鞋子的颜色,鞋子尺码等信息;

    简单的买鞋订阅例子

    var shoeObj = {};
    shoeObj.list = [];
    
    shoeObj.listen = function (key, fn) {
        if (!this.list[key]) {
            this.list[key] = [];
        }
        this.list[key].push(fn)
    }
    
    shoeObj.notify = function () {
        var key = Array.prototype.shift.call(arguments);
        var fns = this.list[key];
    
        if (!fns || fns.length === 0) {
            return;
        }
    
        for (var i = 0, fn; fn = fns[i++];) {
            fn.apply(this, arguments);//附带的参数信息
        }
    }
    
    shoeObj.listen('jiawei', function (size) {
        console.log(`尺码是${size}`);
    })
    
    shoeObj.listen('xianxian', function (size) {
        console.log(`尺码是${size}`);
    })
    
    shoeObj.notify('jiawei', 40);
    shoeObj.notify('xianxian', 42);
    

    封装订阅发布

    var events = {
        list: [],
        listen: function (key, fn) {
            if (!this.list[key]) {
                this.list[key] = [];
            }
            this.list[key].push(fn);
        },
        notify: function () {
            var key = Array.prototype.shift.call(arguments);
            var fns = this.list[key];
            if (!fns || fns.length === 0) {
                return;
            }
    
            for (var i = 0, fn; fn = fns[i++];) {
                fn.apply(this, arguments);
            }
        },
        remove_listen: function (key, fn) {
            var fns = this.list[key];
            if (!fns) {
                return false;
            }
            if (!fn) {
                fns.length === 0;
            }
            for (let i = fns.length - 1; i >= 0; i--) {
                var _fn = fns[i];
                if (_fn === fn) {
                    fns.splice(i, 1);
                }
            }
        }
    }
    
    var initEvent = function (obj) {
        for (var i in events) {
            obj[i] = events[i]
        }
    }
    
    var shoeObj = {};
    initEvent(shoeObj);
    
    shoeObj.listen('jiawei', function (size) {
        console.log(`尺码是${size}`);
    })
    
    shoeObj.listen('xianxian', function (size) {
        console.log(`尺码是${size}`);
    })
    
    shoeObj.remove_listen('jiawei', 40);
    shoeObj.notify('xianxian', 42);
    

    封装一个全局的发布订阅模式

    var EventBus = (function () {
        var list = {},
            listen,
            trigger,
            remove_listen,
    
            listen = function (key, fn) {
                if (!list[key]) {
                    list[key] = [];
                }
                list[key].push(fn);
            };
    
        trigger = function () {
            var key = Array.prototype.shift.call(arguments);
            var fns = list[key];
            if (!fns || fns.length === 0) {
                return;
            }
            for (let i = 0, fn; fn = fns[i++];) {
                fn.apply(this, arguments);
            }
        };
    
        remove_listen = function (key, fn) {
            var fns = list[key];
            if (!fns) {
                return;
            }
            if (!fn) {
                fns.length = 0;
            }
            for (let index = fns.length - 1; index >= 0; index--) {
                var _fn = fns[index];
                if (_fn === fn) {
                    fns.splice(i, 1);
                }
            }
        };
    
        return {
            listen: listen,
            trigger: trigger,
            remove_listen: remove_listen
        }
    })()
    
    EventBus.listen('jiawei', function (size) {
        console.log(size);
    })
    
    EventBus.trigger('jiawei', 43);
    
    展开全文
  • 发布订阅模式与观察者模式

    万次阅读 多人点赞 2019-03-29 18:25:12
    设计模式并非是软件开发的专业术语,实际上,“模式”最早诞生于建筑学。 设计模式的定义是:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。通俗一点说,设计模式是在某种场合下对某个问题的一种...

    背景

    设计模式并非是软件开发的专业术语,实际上,“模式”最早诞生于建筑学。

    设计模式的定义是:在面向对象软件设计过程中针对特定问题的简洁而优雅的解决方案。通俗一点说,设计模式是在某种场合下对某个问题的一种解决方案。如果再通俗一点说,设计模式就是给面向对象软件开发中的一些好的设计取个名字。

    这些“好的设计”并不是谁发明的,而是早已存在于软件开发中。一个稍有经验的程序员也许在不知不觉中数次使用过这些设计模式。GoF(Gang of Four–四人组,《设计模式》几位作者)最大的功绩是把这些“好的设计”从浩瀚的面向对象世界中挑选出来,并且给予它们一个好听又好记的名字。

    设计模式并不直接用来完成代码的编写,而是描述在各种不同情况下,要怎么解决问题的一种方案,他不是一个死的机制,他是一种思想,一种写代码的形式。每种语言对于各种设计模式都有他们自己的实现方式,对于某些设计模式来说,可能在某些语言下并不适用,比如工厂方法模式对于javascript。模式应该用在正确的地方。而哪些才算正确的地方,只有在我们深刻理解了模式的意图之后,再结合项目的实际场景才会知道。。

    模式的社区一直在发展。GoF在1995年提出了23种设计模式,但模式不仅仅局限于这23种,后面增加到了24种。在这20多年的时间里,也许有更多的模式已经被人发现并总结了出来,比如一些JavaScript 图书中会提到模块模式、沙箱模式等。这些“模式”能否被世人公认并流传下来,还有待时间验证。

    观察者模式(Observer Pattern)

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

    观察者模式有一个别名叫“发布-订阅模式”,或者说是“订阅-发布模式”,订阅者和订阅目标是联系在一起的,当订阅目标发生改变时,逐个通知订阅者。我们可以用报纸期刊的订阅来形象的说明,当你订阅了一份报纸,每天都会有一份最新的报纸送到你手上,有多少人订阅报纸,报社就会发多少份报纸,报社和订报纸的客户就是上面文章开头所说的“一对多”的依赖关系。

    发布订阅模式(Pub-Sub Pattern)

    其实24种基本的设计模式中并没有发布订阅模式,上面也说了,他只是观察者模式的一个别称。

    但是经过时间的沉淀,似乎他已经强大了起来,已经独立于观察者模式,成为另外一种不同的设计模式。

    在现在的发布订阅模式中,称为发布者的消息发送者不会将消息直接发送给订阅者,这意味着发布者和订阅者不知道彼此的存在。在发布者和订阅者之间存在第三个组件,称为消息代理或调度中心或中间件,它维持着发布者和订阅者之间的联系,过滤所有发布者传入的消息并相应地分发它们给订阅者。

    举一个例子,你在微博上关注了A,同时其他很多人也关注了A,那么当A发布动态的时候,微博就会为你们推送这条动态。A就是发布者,你是订阅者,微博就是调度中心,你和A是没有直接的消息往来的,全是通过微博来协调的(你的关注,A的发布动态)。

    观察者模式和发布订阅模式有什么区别?

    我们先来看下这两个模式的实现结构:
    模式结构

    观察者模式: 观察者(Observer)直接订阅(Subscribe)主题(Subject),而当主题被激活的时候,会触发(Fire Event)观察者里的事件。

    发布订阅模式: 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Topic),当发布者(Publisher)发布该事件(Publish topic)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

    我们再来看下这两个模式的代码案例:(猎人发布与订阅任务)

    观察者模式:

        //有一家猎人工会,其中每个猎人都具有发布任务(publish),订阅任务(subscribe)的功能
    	//他们都有一个订阅列表来记录谁订阅了自己
    	//定义一个猎人类
    	//包括姓名,级别,订阅列表
    	function Hunter(name, level){
    		this.name = name
    		this.level = level
    		this.list = []
    	}
    	Hunter.prototype.publish = function (money){
    		console.log(this.level + '猎人' + this.name + '寻求帮助')
    	    this.list.forEach(function(item, index){
    	    	item(money)
    	    })
    	}
    	Hunter.prototype.subscribe = function (targrt, fn){
    		console.log(this.level + '猎人' + this.name + '订阅了' + targrt.name)
    	    targrt.list.push(fn)
    	}
    	
    	//猎人工会走来了几个猎人
    	let hunterMing = new Hunter('小明', '黄金')
    	let hunterJin = new Hunter('小金', '白银')
    	let hunterZhang = new Hunter('小张', '黄金')
    	let hunterPeter = new Hunter('Peter', '青铜')
    	
    	//Peter等级较低,可能需要帮助,所以小明,小金,小张都订阅了Peter
    	hunterMing.subscribe(hunterPeter, function(money){
    		console.log('小明表示:' + (money > 200 ? '' : '暂时很忙,不能') + '给予帮助')
    	})
    	hunterJin.subscribe(hunterPeter, function(){
    		console.log('小金表示:给予帮助')
    	})
    	hunterZhang.subscribe(hunterPeter, function(){
    		console.log('小金表示:给予帮助')
    	})
    	
    	//Peter遇到困难,赏金198寻求帮助
    	hunterPeter.publish(198)
    	
    	//猎人们(观察者)关联他们感兴趣的猎人(目标对象),如Peter,当Peter有困难时,会自动通知给他们(观察者)
    

    发布订阅模式:

        //定义一家猎人工会
    	//主要功能包括任务发布大厅(topics),以及订阅任务(subscribe),发布任务(publish)
    	let HunterUnion = {
    		type: 'hunt',
    		topics: Object.create(null),
    		subscribe: function (topic, fn){
    		    if(!this.topics[topic]){
    		      	this.topics[topic] = [];  
    		    }
    		    this.topics[topic].push(fn);
    		},
    		publish: function (topic, money){
    		    if(!this.topics[topic])
    		      	return;
    		    for(let fn of this.topics[topic]){
    		    	fn(money)
    		    }
    		}
    	}
    	
    	//定义一个猎人类
    	//包括姓名,级别
    	function Hunter(name, level){
    		this.name = name
    		this.level = level
    	}
    	//猎人可在猎人工会发布订阅任务
    	Hunter.prototype.subscribe = function (topic, fn){
    		console.log(this.level + '猎人' + this.name + '订阅了狩猎' + topic + '的任务')
    	    HunterUnion.subscribe(topic, fn)
    	}
    	Hunter.prototype.publish = function (topic, money){
    		console.log(this.level + '猎人' + this.name + '发布了狩猎' + topic + '的任务')
    	    HunterUnion.publish(topic, money)
    	}
    	
    	//猎人工会走来了几个猎人
    	let hunterMing = new Hunter('小明', '黄金')
    	let hunterJin = new Hunter('小金', '白银')
    	let hunterZhang = new Hunter('小张', '黄金')
    	let hunterPeter = new Hunter('Peter', '青铜')
    	
    	//小明,小金,小张分别订阅了狩猎tiger的任务
    	hunterMing.subscribe('tiger', function(money){
    		console.log('小明表示:' + (money > 200 ? '' : '不') + '接取任务')
    	})
    	hunterJin.subscribe('tiger', function(money){
    		console.log('小金表示:接取任务')
    	})
    	hunterZhang.subscribe('tiger', function(money){
    		console.log('小张表示:接取任务')
    	})
    	//Peter订阅了狩猎sheep的任务
    	hunterPeter.subscribe('sheep', function(money){
    		console.log('Peter表示:接取任务')
    	})
    	
    	//Peter发布了狩猎tiger的任务
    	hunterPeter.publish('tiger', 198)
    	
    	//猎人们发布(发布者)或订阅(观察者/订阅者)任务都是通过猎人工会(调度中心)关联起来的,他们没有直接的交流。
    

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

    观察者模式由具体目标调度,每个被订阅的目标里面都需要有对观察者的处理,这种处理方式比较直接粗暴,但是会造成代码的冗余。

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

    观察者模式是不是发布订阅模式

    网上关于这个问题的回答,出现了两极分化,有认为发布订阅模式就是观察者模式的,也有认为观察者模式和发布订阅模式是真不一样的。

    其实我不知道发布订阅模式是不是观察者模式,就像我不知道辨别模式的关键是设计意图还是设计结构(理念),虽然《JavaScript设计模式与开发实践》一书中说了分辨模式的关键是意图而不是结构

    如果以结构来分辨模式,发布订阅模式相比观察者模式多了一个中间件订阅器,所以发布订阅模式是不同于观察者模式的;如果以意图来分辨模式,他们都是实现了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知,并自动更新,那么他们就是同一种模式,发布订阅模式是在观察者模式的基础上做的优化升级。

    不过,不管他们是不是同一个设计模式,他们的实现方式确实有差别,我们在使用的时候应该根据场景来判断选择哪个。

    展开全文
  • 主要介绍了C#设计模式订阅发布模式的的相关资料,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
  • 主要介绍了JavaScript设计模式之观察者模式与发布订阅模式,结合实例形式详细分析了JavaScript观察者模式与发布订阅模式相关概念、原理
  • 主要介绍了JS模式之简单的订阅者和发布模式,以一个完整实例形式详细分析了JS订阅者和发布模式基本实现技巧,需要的朋友可以参考下
  • 该例子程序是用C++代码编写,实现了发布-订阅模式;通过该例子可以很好的理解设计模式中的发布-订阅模式的精髓;
  • 上次研究观察者模式,很多文章说它也叫Subscribe/Publish(发布/订阅模式)。可在《Javascript设计模式》一书中,这两种模式还是有些区别的。书中原话如下: 1.Observer模式要求希望接收到主题通知者的观察者必须订阅...
  • Java中使用发布订阅模式

    千次阅读 2020-07-31 16:13:04
    在结构上,观察者模式只有对象和观察者,发布订阅模式中存在 发布者、订阅者以及中间的调度中心。 使用意图 发布订阅者模式可以为对象创建一对多的关系,并在发布者发生改变时通知其订阅者。 使用场景 发布订阅者...

    概述

    发布订阅者模式其实在意图上等同于观察者模式,但是在结构上又有所不同。 在意图上,两者都是为对象创建一对多的关联关系,并且在对象发生改变之后通知其他对象。在结构上,观察者模式只有对象和观察者,发布订阅模式中存在 发布者、订阅者以及中间的调度中心。

    使用意图

    发布订阅者模式可以为对象创建一对多的关系,并在发布者发生改变时通知其订阅者。

    使用场景

    • 发布订阅者使用场景较为广泛,如今我们使用的消息中间件,如 Rocket MQ , Rabbit MQ等都使用到了发布订阅者模式。
    • 在论坛、微博等社交网站中,也很常用的使用到了发布者订阅者模式。一个用户A可以订阅一个用户B,用户B发布了消息之后,通过调度中心C来选择该用户的订阅者进行推送(广播)消息。

    与MVC模式之间的关系

    在MVC模式下, 发布者和订阅者都属于Model,调度中心属于Service,订阅、取消订阅、发布信息都是应该在 Controller层完成。视图层则是用户操作页面。

    逻辑方法展示

    subscriber 
    
    	 ↑
    	
    	
    	SubPub 1.提供订阅、2.取消订阅、3.发布信息等。 
    	1.订阅时发生的事情: 添加 订阅者 id 与发布者 id 的关联信息
    	2.取消订阅时发生的事情: 删除订阅者 id 和 发布者 id 的关联信息
    	3.发布信息发生的事情: 查找 发布者 id 关联的 订阅者 id, 并找到订阅者,进行发送数据。
    	
    	方法定义:
    		1.订阅(提供订阅者和发布者的id)
    		2.取消订阅(提供订阅者和发布者的id)
    		3.
    			3.1 发布信息(发布者id,发布的信息)  --默认所有人可见
    			3.2 发布信息(发布者id,发布的信息,通知人列表) --- 其他的方法可以调用该方法完成
    			3.3 发布信息(发布者id,发布信息,权限类型[所有人可见、部分人可见、好友可见、仅自己可见])  =-=实际上会存在更多的权限类型。简单举例
    	
    	
         ↓
    	 
    publisher
    

    代码演示

    • Publisher
    
    /**
     * @=-= 发布者。模型数据,只需要定义发布者所拥有的属性即可,操作交给控制器。
     */
    public class Publisher {
    
        private Integer id;  //唯一。每个发布者的id都不相同
        
       ///Constructor And Getter\Setter 
    }
    
    • Subscriber
    /**
     * @=-= 订阅者。 模型类,只负责定义数据,将操作转交给控制层。
     */
    public class Subscriber {
    
        private Integer id;   
        
        ///Constructor And Getter\Setter 
    }
    
    • Message
    public class Message {
    
        private String content; 
        ///Constructor And Getter\Setter 
    }
    
    • SubPubCentral
    **
     * @=-= 发布订阅中心。
     */
    public interface SubPubCentral {
    
        public boolean subscribe(Publisher publisher, Subscriber subscriber);
    
        public boolean unsubscribe(Publisher publisher,Subscriber subscriber);
    
        public void publish(Publisher publisher, Message message);
    }
    
    • SubPubCentralImpl
    public class SubPubCentalImpl implements SubPubCentral {
    
        private static Map<Integer, Set<Integer>> PubSubMap ;  //存放所有的发布者的对应订阅者。
    
        static{
            PubSubMap = new HashMap<>();
        }
    
        @Override
        public boolean subscribe(Publisher publisher, Subscriber subscriber) {
    
            try{
                Set<Integer>  subscriberSet = PubSubMap.get(publisher.getId()); //拿到当前发布者的所有订阅者
                if(subscriberSet == null)  //为空,之前不存在订阅者
                    subscriberSet = new HashSet<>();
                boolean added = subscriberSet.add(subscriber.getId()); //添加订阅者
                if(added)  //添加订阅者成功。
                    return PubSubMap.put(publisher.getId(),subscriberSet) != null;
                return false;  //订阅者添加失败或者该订阅之前则订阅了发布者
            }catch(Exception e){
                e.printStackTrace();
            }
            return false;
        }
    
        @Override
        public boolean unsubscribe(Publisher publisher, Subscriber subscriber) {
    
            try{
                Set<Integer>  subscriberSet = PubSubMap.get(publisher.getId());
                if(subscriberSet == null)
                    return false;
                boolean removed = subscriberSet.remove(subscriber.getId());       //删除取消订阅者
                if(removed)
                    PubSubMap.put(publisher.getId(),subscriberSet); //更新订阅者列表
                return removed;
            }catch (Exception e){
                e.printStackTrace();
            }
    
            return false;
        }
    
        @Override
        public void publish(Publisher publisher, Message message) {
    
            Set<Integer> subscriberSet =  PubSubMap.get(publisher.getId());
    
            //遍历订阅者发送消息。 此处简单实现: 只需要打印出拿到的所有订阅者即可
            for (Integer subscriber:
                 subscriberSet) {
                System.out.println("向发布者[" + publisher.getId()
                        +"]的订阅者[" + subscriber + "]发送消息: " +  message);
            }
        }
    }
    
    • SubscriberController
    /***
     * @=-= 控制层,负责控制订阅者的一系列行为。
     */
    public class SubscriberController {
    
        private SubPubCentral subPubCentral;
    
        public SubscriberController(SubPubCentral subPubCentral) {
            this.subPubCentral = subPubCentral;
        }
    
        public void subscribe(Integer subscriberId,Integer publisherId){
            subPubCentral.subscribe(new Publisher(publisherId),new Subscriber(subscriberId));
        }
    
        public void unsubscribe(Integer subscriberId,Integer publisherId){
            subPubCentral.unsubscribe(new Publisher(publisherId),new Subscriber(subscriberId));
        }
    
    }
    
    • PublisherController
    /**
     * @=-= 控制层。负责控制发布者的一系列行为。
     */
    public class PublisherController {
    
        private SubPubCentral subPubCentral;  //订阅发布中心。
    
        public PublisherController(SubPubCentral subPubCentral) {
            this.subPubCentral = subPubCentral;
        }
    
        /**
         * @=-= 发布数据,假设前端传递的是一个id对象和一个内容对象。简单化,实际上会传递一个包装数据过来.
         * @param publisherId
         * @param message
         */
        public void publish(Integer publisherId,String message){
            subPubCentral.publish(new Publisher(publisherId),new Message(message));
        }
    }
    
    • Main
    package cn.tblack.observable;
    
    public class Main {
        /**
         * @=-= 测试发布订阅。模拟事件。
         * @param args
         */
        public static void main(String[] args) {
            SubPubCentral subPubCentral =  new SubPubCentalImpl();
    
    
            PublisherController publisherController = new PublisherController(subPubCentral);
            SubscriberController subscriberController = new SubscriberController(subPubCentral);
    
            subscriberController.subscribe(1,1);
            subscriberController.subscribe(2,1);
    
            publisherController.publish(1,"我今天很好");
    
            System.out.println("\n----------------------------------------------------\n\n");
            subscriberController.unsubscribe(1,1);
            publisherController.publish(1,"我过得很好");
    
        }
    }
    
    

    执行结果:
    在这里插入图片描述

    展开全文
  • JS简单实现发布订阅模式

    千次阅读 2021-01-30 17:36:52
    发布订阅模式发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。 那他们之间如何交流? 由一个调度中心来做中间人,发布者更新(publish)主题,由主题(调度中心)来进行通知...

    在这里插入图片描述

    发布订阅模式

    在发布订阅模式里,发布者,并不会直接通知订阅者,换句话说,发布者和订阅者,彼此互不相识。

    那他们之间如何交流?

    由一个调度中心来做中间人,发布者更新(publish)主题,由主题(调度中心)来进行通知(noticy)订阅者更新(update)。
    在这里插入图片描述

    简单的代码实现

    参考网上class面向对象实现,相较于很多js event的实现便于理解

    // 主题
    class Dep {
      constructor(callback) {
        this.subs = []; // 主题的订阅者
        this.callback = callback;
      }
    
      // 添加订阅者
      addSub(sub) {
        this.subs.push(sub);
        return this;
      }
    
      // 主题更新通知---调用订阅者update,通知所有订阅者
      notify() {
        this.subs.forEach(item => item.update(this.callback));
      }
    }
    
    // 订阅者
    class Sub {
      constructor(val) {
        this.val = val;
      }
    
      update(callback) {
        this.val = callback(this.val); // 执行订阅主题的函数
        console.log('更新之后:', this.val);
      }
    }
    
    // 发布者
    class Pub {
      constructor() {
        this.deps = []; // 发布的主题列表
      }
    
      // 添加主题
      addDep(dep) {
        this.deps.push(dep);
      }
    
      // 移除主题
      removeDep(dep) {
        let index = this.deps.indexOf(dep);
        if (index !== -1) {
          this.deps.splice(index, 1);
          return true;
        } else {
          return false;
        }
      }
    
      // 更新主题
      publish(dep) {
        this.deps.forEach(item => item == dep && item.notify());
      }
    }
    
    // 新建主题,给主题中加订阅者
    let dep1 = new Dep(item => item * item);
    dep1.addSub(new Sub(1)).addSub(new Sub(2)).addSub(new Sub(3));
    
    // 新建发布者
    let pub = new Pub();
    // 添加主题
    pub.addDep(dep1);
    
    // 发布者发布,通知这个主题的所有订阅者更新
    pub.publish(dep1);
    
    // 输出结果
    // 更新之后结果:1
    // 更新之后结果:4
    // 更新之后结果:9
    
    展开全文
  • 手写发布订阅模式 EventEmitter

    千次阅读 2019-10-22 16:28:40
    手写发布订阅模式 EventEmitter 1.简介 最近发现好多大厂面试题里都有手写发布订阅模式 EventEmitter,原因是 vue 和 react 的非父子组件的通信就是靠他实现的,下面是一个简易版的 EventEmitter。 2.代码 // 发布...
  • 发布订阅模式就是发布者发送消息,订阅者接收到消息后进行处理,降低了耦合度,很多业务场景都应用到了这样的场景,比如说下单完成后,可能要还有消息提醒,给予抽奖资格等后续功能,此时就可以使用发布订阅模式处理...
  • Redis实现消息队列之发布订阅模式

    千次阅读 2020-06-18 01:06:09
    发布订阅模式类似与微博关注,比如说博主mango被张三、李四、王五关注,那么mango发一篇微博的时候张李王三人都会从关注里看到这条微博。 那么发布订阅和生产消费有何异同之处呢?生产消费主要是生成一个消息只能被...
  • 主要介绍了浅谈发布订阅模式与观察者模式,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Table of Contents 概念简述 两者区别 流行消息队列的消息模型比较 RabbitMQ ...JMS 规范支持两种消息模型:点到点、发布订阅。...点到点模式:生产者将消息发送到队列中,然后消费者去...发布订阅模式:生产这将消息...
  • Swarm 支持两种服务发布模式两种模式均保证服务从集群外可访问 Ingress模式默认 Host模式 通过 Ingress 模式发布的服务可以保证从 Swarm 集群内任一节点即使没有运行服务的副本都能访问该服务以 Host 模式发布的服务...
  • 发布订阅模式代码实现

    千次阅读 2020-04-26 23:14:12
    发布订阅模式简介:订阅者(Subsciber)通过事件注册(Subscribe)将订阅事件提交到调度中心(Topic),调度中心保存好订阅者的注册信息(回调函数),每当发布者(Publisher)发布事件的时候,通过事件发布(Publish...
  • IE 不支持,性能由浏览器优化 发布订阅模式和观察者模式 发布订阅模式和观察者模式,是两种设计模式,在 Vue 中有各自的应用场景,本质相同,但存在一定的区别。 1,发布/订阅模式 发布/订阅模式 1,订阅者 2,发布...
  • 经典设计模式-发布订阅模式

    千次阅读 2019-03-25 09:34:38
    可能有的人在面试当中被问道过,“观察者模式和发布订阅模式的有什么区别?” 其实一开始我以为这两设计模式是一样的,只是叫法有一些区别,后来随着学习的深入,才发现二者还是有区别的。 观察者模式 我认为...
  • js实现发布订阅模式

    2020-09-06 20:50:08
    定义 发布订阅是一种消息范式,消息的发送者(发布者)不会将消息直接发送给特定的接收者(订阅者),而是将发布的消息发给消息代理,由消息代理对消息进行过滤,消息代理通常执行存储转发的功能将消息从发布者发送...
  • 发布订阅模式的巧妙应用

    千次阅读 2019-04-01 09:26:43
    作为一种优秀的设计模式,发布订阅模式被广泛的应用在前端领域。举个例子,在 vue 的源码中,为了让数据劫持和视图驱动解耦就是通过架设一层消息管理层实现的,而这一层消息管理层实现的原理就是发布订阅模式。再...
  • react 中发布订阅模式使用

    千次阅读 2018-12-20 21:23:50
    react 中发布订阅模式使用 场景 怎么能将设计模式应用到我们的 React 项目中?以前一直在思考这个问题。 场景一 模块 A 模块 B 需要用到同一个数据 data,A 和 B 都会修改这份数据,且这两个模块会同时存在;...
  • 本篇介绍发布订阅模式 发布订阅模式 发布/订阅模式是指同时向多个消费者发送消息的模式(类似广播的形式),它包含一个生产者、两个消费者、两个队列和一个交换机。两个消费者同时绑定到不同的队列上去,两个队列...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 138,903
精华内容 55,561
关键字:

发布订阅模式