观察者模式的一个例子

观察者模式(有时又被称为发布-订阅模式、模型-视图模式、源-收听者

模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件,并且在它本身的状态改变时主动发出通知。这通常透过呼叫各观察者所提供的方法来实现。此种模式通常被用来实作事件处理系统。

观察者模式(Observer)完美的将观察者和被观察的对象分离开。举个例子,用户界面可以作为一个观察者,业务数据是被观察者,用户界面观察业务数据的变化,发现数据变化后,就显示在界面上。面向对象设计的一个原则是:系统中的每个类将重点放在某一个功能上,而不是其他方面。一个对象只做一件事情,并且将他做好。观察者模式在模块之间划定了清晰的界限,提高了应用程序的可维护性和重用性。
下面,我是在他人基础上做的一个封装以及简单继承。
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8"/>
</head>
<body>
<button id="sendWeekly">发送周报</button>
<button id="sendDaily">发送日报</button>
<script>
    var inherits = function (ctor, superCtor) {
        // 显式的指定父类
        ctor.super_ = superCtor;
        superCtor = typeof superCtor === "function" ? superCtor.prototype : superCtor;
        // ECMAScript 5  原型式继承并解除引用
        if (Object.create) {
            ctor.prototype = Object.create(superCtor, {
                constructor:{
                    value:ctor,
                    enumerable:false,
                    writable:true,
                    configurable:true
                }
            });
        } else {
            // 无Object.create方法的平稳退化
            function F() {
            };
            F.prototype = superCtor;
            ctor.prototype = new F();
            ctor.prototype.constructor = ctor;
        }
    };

    var Observer = (function (W) {
        var pubsub = function () {
            this.topics = {};
            this.subUid = -1;
        };

        // 发布方法
        pubsub.prototype.fire = function (type) {
            var args = [].slice.call(arguments, 1),
                    that = this;
            if (!this.topics[type]) {
                return false;
            }
            (function () {
                var subscribers = that.topics[type],
                        len = subscribers ? subscribers.length : 0;

                while (len--) {
                    subscribers[len].func.apply(that, args);
                }
            })();

            return true;
        };
        //订阅方法
        pubsub.prototype.on = function (type, fn) {
            if (!this.topics[type]) {
                this.topics[type] = [];
            }

            var token = (++this.subUid).toString();
            this.topics[type].push({
                token:token,
                func:fn
            });
            return token;
        };
        //退订方法
        pubsub.prototype.off = function (type, token) {
            var evT;
            if (type === void 0) {
                return this.topics = {}
            }

            if (arguments.length == 1) {
                if (!this.topics[type]) {
                    return;
                }
                return delete this.topics[type];
            }
            evT = this.topics[type];
            for (var i = 0, j = evT.length; i < j; i++) {
                if (evT[i].token === token) {
                    evT.splice(i, 1);
                    return token;
                }
            }
            return false;
        };
        return pubsub;
    }(window));


    function Paper(name, pages, price) {
        this.name = name;
        this.pages = pages;
        this.price = price;
    }

    inherits(Paper, new Observer);

    Paper.prototype.send = function (topic) {
        this.fire(topic, {
            name:this.name,
            pages:this.pages,
            price:this.price
        });
    };

    function Person(name) {
        var that = this;
        this.name = name;
        this.recive = function (paper) {
            console.log(that.name + ' recive Pager detail:\n' + 'name:' + paper.name + '\npages:' + paper.pages + '\nprice:' + paper.price)
        }
    }

    var person = new Person('Lucy'),
            person1 = new Person('Tom');
    var Weekly = new Paper('weekly', 298, '$6'),
            Daily = new Paper('daily', 7, '$0.8');

    var pr = Weekly.on('weekly', person.recive),
            pr1 = Weekly.on('weekly', person1.recive);
    var pr2 = Daily.on('daily', person.recive);

    var $ = function (id) {
        return document.getElementById(id);
    }

    $('sendWeekly').onclick = function () {
        Weekly.send('weekly');
    }

    $('sendDaily').onclick = function () {
        Daily.send('daily');
    }
</script>
</body>
</html>

 

posted @ 2013-04-02 15:27  穆乙  阅读(599)  评论(0编辑  收藏  举报