一. 概述

  有时被称作发布/订阅模式,观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

二. 使用观察者模式的好处

  1、 支持简单的广播通信,自动通知所有已经订阅过的对象。
  2、 页面载入后目标对象很容易与观察者存在一种动态关联,增加了灵活性。
  3、 目标对象与观察者之间的抽象耦合关系能够单独扩展以及重用。


三. code


(function(slice) {
    function Observer() {
        this.events = {}
    }
    Observer.prototype = {
        subscribe: function(signals, fn) {
            signals = signals.split(' ')
            signals.forEach(function(signal) {
                if (!this.events[signal]) {
                    this.events[signal] = []
                }
                fn && (this.events[signal].push(fn))
            }
            .bind(this))
        },
        publish: function(signals) {
            var args = slice.call(arguments, 1)
            signals = signals.split(' ')
            signals.forEach(function(signal) {
                var events = this.events[signal]
                if (events) {
                    events.forEach(function(fn) {
                        fn.apply(this, args)
                    })
                }
            }
            .bind(this))
        },
        unsubscribe: function(signal, fn) {
            var events = this.events[signal]
            if (events) {
                events.forEach(function(fn) {
                    events.splice(events.indexOf(fn), 1)
                }
                .bind(this))
            }
        }
    }
    window.Observer = Observer
})(Array.prototype.slice);

// 创建 var workday = new Observer()

// 订阅 var gowork = workday.subscribe('9点 10点', function(name) { console.log(name + '上班时间到啦。') }) var offwork = workday.subscribe('17点 18点', function(name) { console.log(name + '下班时间到啦。') }) var eat = workday.subscribe('19点', function(name) { console.log(name + '吃饭时间到啦。') }) var read = workday.subscribe('19点', function(name) { console.log(name + '看书时间到啦。') })

// 取消订阅 workday.unsubscribe('19点', eat)

// 发布订阅 workday.publish('19点', 'Tony')

var hours = new Date().getHours() if (hours > 9 && hours < 17) { workday.publish('9点', 'Tony') } else { workday.publish('17点', 'Tony') }