Javascript模式(二) 发布者/订阅者模式
var publisher = {
// 订阅者数组
subscribers : {
"any" : []
},
// 增加订阅者
on : function(type, fn, context){
var subscribers = this.subscribers;
type = type || "any";
context = context || this;
fn = typeof fn === "function" ? fn : context[fn];
if(!subscribers[type]){
subscribers[type] = [];
}
subscribers[type].push({"fn" : fn, "context" : context});
},
// 移除订阅者
off : function(type, fn, context){
this.visit("unPublish", type, fn, context)
},
// 通知
fire : function(type, arg){
this.visit("publish", type, arg);
},
// 访问订阅者数组
visit : function(action, type, arg, context){
var subscribers, i, len;
type = type || "any";
subscribers = this.subscribers[type];
len = subscribers.length || 0;
switch(action){
case "publish" :
for(i = 0; i < len; i++){
subscribers[i].fn.call(subscribers[i].context, arg);
}
break;
case "unPublish":
for(i = 0; i < len; i++){
if(subscribers[i].fn === arg && subscribers[i].context === context){
subscribers.splice(i, 1);
}
}
break;
}
}
};
function makePublisher(o){
o.subscribers = {"any" : []};
for(var p in publisher ){
if(publisher.hasOwnProperty(p) && typeof publisher[p] === "function"){
o[p] = publisher[p];
}
}
return o;
}
// 发布者Play
// 发布两个事件:1、有玩家加入 2、玩家开始玩
function Player(name, key){
this.point = 0;
this.name = name;
this.key = key;
this.fire("add", this);
}
Player.prototype.play = function(){
this.point += 1;
this.fire("play", this);
};
// 观察者/订阅者 game,观察2个事件:1、有玩家加入 2、玩家开始玩
// 同时作为发布者game,通知积分榜更新
var game = {
// 存储对象和按键key的关系
keys : {},
// 订阅
addPlayer : function(player){
this.keys[player.key] = player;
},
// 通知订阅者scoreboard更新
handlyPlay : function(){
var score = {}, keys = this.keys, p;
for(p in keys){
if(keys.hasOwnProperty(p)){
score[keys[p].name] = keys[p].point;
}
}
this.fire("update", score);
},
// 封装keypress事件
keydown : function(e){
var which, code;
e = e || event;
which = e.which || e.keyCode;
code = String.fromCharCode(which);
if(this.keys[code]){
this.keys[code].play();
}
}
};
// 积分榜
var scoreboard = {
dom : document.getElementById("score_board"),
// 更新积分榜 参数格式 {playname1 : point, playname2 : point }
update : function(score){
var p, html = "";
for(p in score){
if(score.hasOwnProperty(p)){
html += p + "获得了" + score[p] + "<br/>";
}
}
this.dom.innerHTML = html;
}
};
// Player作为发布者,因其需要通知订阅者game新增玩家以及玩家积分变化
// game对Player而言是订阅者,因其需要订阅Player的特定活动add(新增玩家)和play(玩家积分发生变化)
// game对scoreboard而言是发布者,因其在观察到Player的play事件之后需要通知scoreboard更新积分
makePublisher(Player.prototype);
makePublisher(game);
Player.prototype.on("add", game.addPlayer, game);
Player.prototype.on("play", game.handlyPlay, game);
game.on("update", scoreboard.update, scoreboard);
//excute
while(true){
var name = prompt("say your name, man"), key;
if(name && name !== "null"){
while(true){
key = prompt("what is your key");
if(key && key !== "null"){
break;
}
alert("亲,还是指定个key吧,不然你没办法玩的,相信我");
}
new Player(name, key);
}
else {
break;
}
}
document.onkeydown = function(e){
game.keydown.call(game, e);
};
Javascript模式(二) 发布者/订阅者模式的更多相关文章
- JavaScript 设计模式: 发布者-订阅者模式
JavaScript 设计模式: 发布者-订阅者模式 发布者-订阅者模式 https://github.com/Kelichao/javascript.basics/issues/22 https:/ ...
- vue双向绑定(数据劫持+发布者-订阅者模式)
参考文献:https://www.cnblogs.com/libin-1/p/6893712.html 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据. 关键点在于data如何更新v ...
- EventBus事件总线框架(发布者/订阅者模式,观察者模式)
一. android应用内消息传递的方式: 1. handler方式-----------------不同线程间传递消息. 2. Interface接口回调方式-------任意两个对象. 3. In ...
- C#事件支持发布者/订阅者模式(观察者模式)
C#事件支持发布者/订阅者模式,发布者将事件通知给订阅者,而订阅者在事件发生时调用已经注册好的事件处理函数. public delegate void delUpdate(); //委 ...
- 学习javascript设计模式之发布-订阅(观察者)模式
1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...
- 用原生javascript实现最简单的发布者-订阅者模式
http://www.cnblogs.com/surahe/p/6065778.html 发布—订阅模式可以广泛应用于异步编程中,这是一种替代传递回调函数的方案.比如,我们可以订阅 ajax 请求的 ...
- 发布者订阅者模式之JAVA实现
1.发布者接口 package com.shoshana.publishsubscribe; public interface IPublisher<M> { public voi ...
- js中的观察者模式与发布者/订阅者模式的区别?
- .netcore利用DI实现订阅者模式 - xms
结合DI,实现发布者与订阅者的解耦,属于本次事务的对象主体不应定义为订阅者,因为订阅者不应与发布者产生任何关联 一.发布者订阅者模式 发布者发出一个事件主题,一个或多个订阅者接收这个事件,中间通过事件 ...
随机推荐
- [暑假集训--数论]poj1365 Prime Land
Everybody in the Prime Land is using a prime base number system. In this system, each positive integ ...
- Python之面向对象:属性
一.属性定义 1.类属性 类属性定义在类中且在函数体之外:类属性通常不作为实例属性使用:类变量紧接在类名后面定义 类属性的引用:类名.count eg:Employee.count 实例中可以引用类的 ...
- Python之文件操作:经验总结
1.怎么判断读出来的文件是gbk还是utf-8编码 if content == u'中国'.encode('gbk'): return 'gbk' elif content == u'中国'. ...
- MYSQL常用命令——【转】
MYSQL常用命令 1.导出整个数据库mysqldump -u 用户名 -p --default-character-set=latin1 数据库名 > 导出的文件名(数据库默认编码是latin ...
- 【HDOJ1828&&POJ1177】Picture(线段树,扫描线)
题意:给定n个矩形,求他们的并的周长 n<=5e3,abs(x[i])<=1e4 思路:From https://www.cnblogs.com/kuangbin/archive/2013 ...
- CentOS 基本操作
1.Vi 基本操作 1) 进入vi 在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面: $ vi myfile 进入vi之后,是处于「命令行模式(command mode)」,您要切 ...
- linux内核情景分析之命名管道
管道是一种"无名","无形文件,只可以近亲进程使用,不可以再任意两个进程通信使用,所以只能实现"有名","有形"的文件来实现就可以 ...
- css 之 position定位
position属性一共有4个值,分别是static.absolute.relative.fixed. static为默认值,指块保持在原本应该在的位置上,即该值没有任何移动的效果. absolute ...
- javascript 获取焦点和失去焦点事件
利用传参的方式提高方法的复用性 这里涉及到JavaScript的字符串拼接操作 </tr> <<tr height="40px"> <td> ...
- js坑 把数字型的字符串默认为数字 把前面的0给去掉了("001")
<script> b("); function b(id) { console.log("b函数的id:"+id); //var history = &quo ...