zoukankan      html  css  js  c++  java
  • 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);
    };
  • 相关阅读:
    ACL最大权限及相关命令
    ACL权限设置
    Linux权限管理--ACL权限简介
    Linux用户信息文件/etc/passwd
    本地光盘yum源的搭建
    响应式 和 移动 web
    svg
    vi 命令
    html 语法
    运营给的广告设计稿如何做
  • 原文地址:https://www.cnblogs.com/mr189/p/3954068.html
Copyright © 2011-2022 走看看