js-发布订阅

2017-01-06  本文已影响0人  LyNnJeR31

最近在学习js的设计模式,写了个demo.
订阅发布模式如果按数学翻译其实就是.一对多的映射关系.怎么解释呢? 就是一个开关,同时并联几个灯泡(在不同房间),触发的时候,几个灯泡都会得到指令,然后执行发光的行为。

  1. 观察者模式中,目标对象负责维护观察者。发布/订阅模式中发布者不关心订阅者,只负责把消息丢出去就不管了。
  1. 观察者模式中,观察者要提供一个接口,然后当目标对象发生改变时调用此接口使自身状态和目标状态保持一致。即所有的观察者都要有一个统一的接口(比如上文中写的update方法,大家的方法都要叫这个名字)。而发布/订阅模式中,订阅者事件的触发不是依靠这样一个接口,而是订阅者通过监听一个特定的消息(这个消息一般包含名称和订阅者所需要的参数)来触发的。可以理解为订阅者监听的不是发布者,而是消息池,只要消息池里有它关心的消息,即触发事件,不管这个消息是谁发布过去的。发布者和订阅者是解耦的。
<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <style type="text/css">
        ul {
            list-style: none;
        }
        
        li {
            width: 150px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            background: orangered;
        }
        
        li:nth-child(2n-1){
            background: orange;
        }
    </style>

    <body>

        <span>最新发布消息</span> 消息:<span id="msg_num">0</span>
        <ul id="msg">

        </ul>
        <textarea name="" rows="" cols="" id="user_input"></textarea>
        <button id="user_submit">提交</button>
    </body>
    <script src="pubsub.js" type="text/javascript" charset="utf-8"></script>
    <script src="demo01.js" type="text/javascript" charset="utf-8"></script>
    <script type="text/javascript">
        //测试
        Observer.regist('test', function(e) {
            console.log(e.type, e.args.msg);
        });
        Observer.fire('test', {
            msg: 'just for test'
        });
    </script>

</html>
//外观模式 简化获取元素
function $(id) {
    return document.getElementById(id);
}

//追加消息
(function() {
    function addMsgItem(e) {
        var text = e.args.text,
            ul = $('msg'),
            li = document.createElement('li'),
            span = document.createElement('span');
        li.innerHTML = text;
        span.innerHTML = '×',
        span.style.cursor = 'pointer';
        
        //关闭按钮
        span.onclick = function() {
                ul.removeChild(li);
                //发布删除留言消息
                Observer.fire('removeCommentMessage', {
                    num: -1
                });
            }
            //添加删除按钮
        li.appendChild(span);
        //添加留言节点
        ul.appendChild(li);
    }
    //注册添加留言信息
    Observer.regist('addCommentMessage', addMsgItem);

})();

//数量
(function() {
    //更改用户信息数目
    function changeMsgNum(e) {
        //获取数目
        var num = e.args.num;
        $('msg_num').innerHTML = parseInt($('msg_num').innerHTML) + num;
    }
    //注册
    Observer.regist('addCommentMessage', changeMsgNum)
    Observer.regist('removeCommentMessage', changeMsgNum)
})();

//提交消息
(function() {
    //提交信息
    $('user_submit').onclick = function() {
        var text = $('user_input');
        if(text.value === '') {
            return;
        }
        //发布一条消息
        Observer.fire('addCommentMessage', {
            text: text.value,
            num: 1
        });
        text.value = '';
    }

})();
//观察者模式
var Observer = (function() {
    var _message = {};
    return {
        //注册信息接口
        regist: function(type, fn) {
            //如果消息不存在,则创建一个该消息类型
            if(typeof _message[type] === 'undefined') {
                _message[type] = [fn];
            } else {
                _message[type].push(fn);
            }
        },
        //发布信息接口
        fire: function(type, args) {
            //如果该消息没有被注册,返回
            if(!_message[type]) {
                return;
            }
            //定义消息信息
            var events = {
                    type: type,
                    args: args || {}
                },
                i = 0,
                len = _message[type].length;
            for(; i < len; i++) {
                //依次执行注册的消息对应的动作序列
                _message[type][i].call(this, events);
            }
        },
        //移除信息接口
        remove: function(type, fn) {
            //如果消息动作队列存在
            if(_message[type] instanceof Array) {
                //从最后一个消息动作遍历
                var i = _message[type].length - 1;
                for(; i >= 0; i--) {
                    //如果村咋该动作则在消息序列中移除相应动作
                    _message[type][i] === fn && _message[type].splice(i, 1);
                }
            }
        }
    }
})();

新手上路,多多指教

上一篇下一篇

猜你喜欢

热点阅读