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模式(二) 发布者/订阅者模式的更多相关文章

  1. JavaScript 设计模式: 发布者-订阅者模式

    JavaScript 设计模式: 发布者-订阅者模式 发布者-订阅者模式 https://github.com/Kelichao/javascript.basics/issues/22 https:/ ...

  2. vue双向绑定(数据劫持+发布者-订阅者模式)

    参考文献:https://www.cnblogs.com/libin-1/p/6893712.html 实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据. 关键点在于data如何更新v ...

  3. EventBus事件总线框架(发布者/订阅者模式,观察者模式)

    一. android应用内消息传递的方式: 1. handler方式-----------------不同线程间传递消息. 2. Interface接口回调方式-------任意两个对象. 3. In ...

  4. C#事件支持发布者/订阅者模式(观察者模式)

    C#事件支持发布者/订阅者模式,发布者将事件通知给订阅者,而订阅者在事件发生时调用已经注册好的事件处理函数.        public delegate void delUpdate();  //委 ...

  5. 学习javascript设计模式之发布-订阅(观察者)模式

    1.发布-订阅模式又叫观察者模式,它定义对象之间一种一对多的依赖关系. 2.如何实现发布-订阅模式 2-1.首先指定好发布者 2-2.给发布者添加一个缓冲列表,用户存放回调函数以便通知订阅者 2-3. ...

  6. 用原生javascript实现最简单的发布者-订阅者模式

    http://www.cnblogs.com/surahe/p/6065778.html 发布—订阅模式可以广泛应用于异步编程中,这是一种替代传递回调函数的方案.比如,我们可以订阅 ajax 请求的 ...

  7. 发布者订阅者模式之JAVA实现

        1.发布者接口 package com.shoshana.publishsubscribe; public interface IPublisher<M> { public voi ...

  8. js中的观察者模式与发布者/订阅者模式的区别?

  9. .netcore利用DI实现订阅者模式 - xms

    结合DI,实现发布者与订阅者的解耦,属于本次事务的对象主体不应定义为订阅者,因为订阅者不应与发布者产生任何关联 一.发布者订阅者模式 发布者发出一个事件主题,一个或多个订阅者接收这个事件,中间通过事件 ...

随机推荐

  1. [暑假集训--数论]poj1365 Prime Land

    Everybody in the Prime Land is using a prime base number system. In this system, each positive integ ...

  2. Python之面向对象:属性

    一.属性定义 1.类属性 类属性定义在类中且在函数体之外:类属性通常不作为实例属性使用:类变量紧接在类名后面定义 类属性的引用:类名.count eg:Employee.count 实例中可以引用类的 ...

  3. Python之文件操作:经验总结

    1.怎么判断读出来的文件是gbk还是utf-8编码 if content == u'中国'.encode('gbk'):     return 'gbk' elif content == u'中国'. ...

  4. MYSQL常用命令——【转】

    MYSQL常用命令 1.导出整个数据库mysqldump -u 用户名 -p --default-character-set=latin1 数据库名 > 导出的文件名(数据库默认编码是latin ...

  5. 【HDOJ1828&&POJ1177】Picture(线段树,扫描线)

    题意:给定n个矩形,求他们的并的周长 n<=5e3,abs(x[i])<=1e4 思路:From https://www.cnblogs.com/kuangbin/archive/2013 ...

  6. CentOS 基本操作

    1.Vi 基本操作 1) 进入vi  在系统提示符号输入vi及文件名称后,就进入vi全屏幕编辑画面:  $ vi myfile  进入vi之后,是处于「命令行模式(command mode)」,您要切 ...

  7. linux内核情景分析之命名管道

    管道是一种"无名","无形文件,只可以近亲进程使用,不可以再任意两个进程通信使用,所以只能实现"有名","有形"的文件来实现就可以 ...

  8. css 之 position定位

    position属性一共有4个值,分别是static.absolute.relative.fixed. static为默认值,指块保持在原本应该在的位置上,即该值没有任何移动的效果. absolute ...

  9. javascript 获取焦点和失去焦点事件

    利用传参的方式提高方法的复用性 这里涉及到JavaScript的字符串拼接操作 </tr> <<tr height="40px"> <td> ...

  10. js坑 把数字型的字符串默认为数字 把前面的0给去掉了("001")

    <script> b("); function b(id) { console.log("b函数的id:"+id); //var history = &quo ...