技术标签: java 发布订阅模式应用
什么是发布订阅模式
什么是发布订阅模式我这里不多就不多阐述了,给大家提供几个我觉得讲的比较好的博文,请各位自行阅读
发布-订阅模式解释 这一篇文章应该是一个java coder写的,但是设计模式这种东西并不分语言,各位可以借鉴一下
Javascript中理解发布--订阅模式这一篇是我们前端人写的,但是比较长,大家有耐心可以看看
发布中心实现
我对发布中心的实现,可以不看(看了能够更好的理解发布订阅模式)
//实现发布中心
/*
* log=[{
* index: Number, 日志编号(自增)
* type: String, 日志类型('subscribe','unsubscribe','publish')
* eventName: String, 事件名
* time: new Date(), 时间
* fun:Function 订阅/取订的方法(只有日志类型为'subscribe'或'unsubscribe'的才有)
* param:Object 触发事件时的参数(只有日志类型为'publish'的才有)
* }]
* eventCenter = {
* eventName:[Function,Function] //eventName即为事件名,其值为订阅方法列表
* }
* .subscribe(eventName, fun) 订阅 eventName:事件名 fun:订阅方法
* .unsubscribe(eventName, fun) 取订 eventName:事件名 fun:订阅方法
* .publish(eventName[,param]) 发布 eventName:事件名 param:事件参数
* .showLog([filter]) 日志展示 filter 过滤器,同数组的过滤器用法 返回过滤后的log
* .showEventCenter([eventName]) 事件中心 eventName 事件名 返回事件绑定的方法
* */
let subscribeCenter = function () {
//事件中心
let eventCenter = {};
//日志
let log = [];
//添加日志函数
function pushLog(type, eventName, fun, param) {
let info = {
index: log.length,
type: type,
eventName: eventName,
time: new Date()
};
if (fun) {
info.fun = fun;
}
if (param) {
info.param = param;
}
log.push(info)
}
return {
//订阅
subscribe(eventName, fun) {
pushLog("subscribe", eventName, fun);
eventCenter[eventName] = eventCenter[eventName] || [];
eventCenter[eventName].push(fun);
},
//取消订阅
unsubscribe(eventName, fun) {
pushLog("unsubscribe", eventName, fun);
let onList = eventCenter[eventName];
if (onList) {
for (let i = 0; i < onList.length; i++) {
if (onList[i] === fun) {
onList.splice(i, 1);
return
}
}
}
},
//发布
publish(eventName, param) {
pushLog("publish", eventName, null, param)
let onList = eventCenter[eventName];
if (onList) {
for (let i = 0; i < onList.length; i++) {
onList[i](param)
}
}
},
//显示日志
showLog(filter) {
filter = filter || (() => true);
let returnLog = log.filter(filter);
returnLog.forEach(x => {
let y = {};
for (let key in x) {
y[key] = x[key]
}
return y
});
return returnLog;
},
//显示事件中心
showEventCenter(eventName) {
let selectEM = eventName ? eventCenter[eventName] : eventCenter, returnEM = {};
for (let key in selectEM) {
returnEM[key] = [];
selectEM[key].forEach(x => {
returnEM[key].push(x)
});
}
return returnEM
}
}
}();
如果有看我上一篇文章中事件监听实现的朋友应该对这个不部分代码有一种熟悉的感觉,确实事件监听和发布订阅的实现非常的像。我主要多做的就是一个日志的拓展,保证了每次的动作都可以被监听和查看;
发布中心API
这个在上面是有的,但是因为上面的部分有一些同学是不看的,所以就在这里摘出来,方便这些同学了解发布中心的用法
/*
* log=[{
* index: Number, 日志编号(自增)
* type: String, 日志类型('subscribe','unsubscribe','publish')
* eventName: String, 事件名
* time: new Date(), 时间
* fun:Function 订阅/取订的方法(只有日志类型为'subscribe'或'unsubscribe'的才有)
* param:Object 触发事件时的参数(只有日志类型为'publish'的才有)
* }]
* eventCenter = {
* eventName:[Function,Function] //eventName即为事件名,其值为订阅方法列表
* }
* .subscribe(eventName, fun) 订阅 eventName:事件名 fun:订阅方法
* .unsubscribe(eventName, fun) 取订 eventName:事件名 fun:订阅方法
* .publish(eventName[,param]) 发布 eventName:事件名 param:事件参数
* .showLog([filter]) 日志展示 filter 过滤器,同数组的过滤器用法 返回过滤后的log
* .showEventCenter([eventName]) 事件中心 eventName 事件名 返回事件绑定的方法
* */
发布/订阅模式在异步中的应用
这里是重点,需要大家仔细看,理解了这段代码不光可以解决异步问题,还可以理解发布订阅者模式是如何应用的;
//发布者
let f1 = function () {
setTimeout(function () {
console.log("'done' 事件发布 参数:", 123);
subscribeCenter.publish("done", 123);
console.log("事件中心", subscribeCenter.showEventCenter());
console.log("f3 取订 'done'");
subscribeCenter.unsubscribe("done", f3);
setTimeout(function () {
console.log("'done' 事件发布 参数:", 233);
subscribeCenter.publish("done", 233);
console.log("事件中心", subscribeCenter.showEventCenter());
console.log("日志", subscribeCenter.showLog());
}, 100)
}, 100)
};
//订阅者
let f2 = function (param) {
console.log("f2 is running, param is", param);
};
//订阅者
let f3 = function (param) {
console.log("f3 is running, param is", param)
};
//订阅
console.log("f2 订阅 'done'");
subscribeCenter.subscribe("done", f2);
console.log("f3 订阅 'done'");
subscribeCenter.subscribe("done", f3);
//发布
f1();
先贴运行结果
在这里可以看到,该模式与事件监听模式非常相似,但是所有的发布都通过了同一个发布中心来控制,这样的话可以方便我们追踪整个事件的状态;
文章浏览阅读725次。Introduction to Udacity Self-Driving Car SimulatorUdacity recently made its self-driving car simulator source code available on their GitHub which was originally built to teach their Self-Drivin..._udacity self driving car sim ros
文章浏览阅读6k次。函数定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可函数特性:def my_sum(x,y): #定义函数名res = x+yreturn res #返回函数执行结果c = my_sum(4,5) #结果赋值给c变量print(c)减少重复代码使程序变的可扩展使程序变得易维护函数参数形参即变量名就是函数定义阶段的参数,实参即变量值就是函数调用阶..._python res
文章浏览阅读607次。动作标签实例之后补齐基础知识scope属性 该属性指定了所创建Bean实例的存取范围,省略该属性时的值为page.标识被执行时,首先会在scope属性指定的范围来查找指定的Bean实例,如果该实例已经存在,则引用这个Bean,否则重新创建,并将其存储在scope属性指定的范围内。 scope属性可选值如下page:(当前页面范围) 制定了所创建的Bean实例只能够在当前的JSP文件中使用,包括在通...
文章浏览阅读2.3w次,点赞6次,收藏55次。实现效果假设000001、000012、000123、002345、600356、600378为某些上市公司证券代码,上市公司实证研究中,常常需要用到上市公司证券代码,将字符型转为数值型比较容易,直接用destring命令即可实现,但是数值型转为字符型并且补齐6位数的命令比较少见。字符型转为数值型destring Stkcd,replace数值型转为字符型tostring Stkc..._stata行业代码变成数值型
文章浏览阅读3.5k次,点赞4次,收藏14次。僵尸进程产生原因了解:僵尸进程是指完成执行通过exit系统调用,或运行时发生致命错误或收到终止信号所致,但在操作系统进程表中仍然有一个表项,处于“终止状态”的进程。这发生于子进程需要保留表项以允许其父进程读取子进程的exit status:一旦退出态通过wait系统调用读取,僵尸进程条目就从进程表中删除,这个过程被称为reap。正常情况下,进程直接被其父进程wait并由系统回收,进程长时间保持僵..._shell脚本执行exit 1 执行后进程变成僵尸进程
文章浏览阅读2.4k次。·不要忘了相机自带的HDR功能目前很多相机都自带了HDR功能,我们以佳能EOS6D为例,首先将该机顶部的模式拨盘转动到SCN档位,然后按Q键选择拍摄模式,其中就有一个模式叫做HDR逆光控制。首先将相机的拨盘转动到SCN模式选择HDR逆光控制选项在此模式下,相机会快速的连拍三次,然后通过机内的处理将所拍摄的这三张照片合成为一张,可以在一定程度上改善照片高光/阴影的细节。没有启用HDR功能..._佳能6d为什么会连拍三张合成一张
文章浏览阅读5.6k次,点赞3次,收藏4次。废话不多说: DateFormatdf=newSimpleDateFormat("yyyy-MM-ddHH:mm:ss"); try { Dated1=df.parse("2018-03-2613:31:40"); Dated2=df.parse("2018-01-0211:30:24");..._java两个时间相减得到分钟
文章浏览阅读130次。PHP性能优化工具–xhprof安装,这里我先贴出大致的步骤:1.获取xhprof2.编译前预处理3.编译安装4.配置php.ini5.查看运行结果那么下面我们开始安装xhprof工具吧:1.获取xhprof可以输入网址直接下载,或者wget1234#wget http://p..._php 安装xprof
文章浏览阅读847次。RK3399-android7.1-mipi转lvds_struct video_timing video_1920x1080_60hz
文章浏览阅读434次。一个正则表达式的教程可以参看(里面有个测试正则表达式的工具)正则表达是用来匹配字符串的好东东。如果用户熟悉Linux下的sed、awk、grep或vi,那么对正则表达式这一概念肯定不会陌生。由于它可以极大地简化处理字符串时的复杂度,因此现 在已经在许多Linux实用工具中得到了应用。千万不要以为正则表达式只是Perl、Python、Bash等脚本语言的专利,作为C语言程序员,用户同 样可以在自己的..._用正则表达定义变量
文章浏览阅读1.5w次,点赞4次,收藏20次。网页自动刷新功能在web网站上已经屡见不鲜了,如即时新闻信息,股票信息等,都需要不断获取最新信息。在传统的web实现方式中,想要实现类似的效果,必须进行整个页面的刷新,在网络速度受到一定限制的情况下,这种因为一个局部变动而牵动整个页面的处理方式显得有些得不偿失。Ajax技术的出现很好的解决了这个问题,利用Ajax技术可以实现网页的局部刷新,只更新指定的数据,并不更新其他的数据。 现在创建一_ajax页面自动刷新
文章浏览阅读5.5w次。情况描述此状况发生在Chrome 的较旧的版本上:机器已经安装过JRE 或是JDK, 但是每次打开Chrome 浏览器使用Applet时, 会报需要下载JRE的提示信息(最新的JRE1.7)。看上去, Chrome 并没有找到系统已经安装的JRE。相比而言, 对于IE和Firefox 浏览器。我们可以在Java 控制台设置使用的JRE版本和支持的浏览器, 而且我们可以更改浏览器_chrome jre