观察者模式

概述

观察者模式, 是使用频率极高的设计模式, 它用于建立一种对象与对象之间的依赖关系,一个对象发生了改变时将自动通知其他对象,其他对象将做出相应反应。
在观察者模式中,发生改变的对象被称为被观察对象(Subject),而被通知的对象被称为观察者(Observer),观察者与被观察对象是N:1的关系,观察者之间可以没有任何关联, 观察者可以根据需求新增或者删除,便于扩展。

结构

示例(ES6)

class ObserverList {
    constructor() {
        this.observerList = [];
    }
    add(observer) {
        return this.observerList.push(observer);
    }
    remove(observer) {
        const index = this.observerList.indexOf(observer);
        return this.observer.splice(index, 1);
    }
}

class Subject {
    constructor() {
        this.observers = new ObserverList();
    }
    addObserver(observer) {
        return this.observers.add(observer);
    }
    deleteObserver(observer) {
        return this.observers.remove(observer);
    }
    notify(context) {
        this.observers.observerList.map((observer) => {
            observer.update(context);
        });
    }
}

class Observer {
    update(context) {

    }
}

html

<button>Add a new Observer</button>
<input type="checkbox" id="mainCheckBox">
<div id="container"></div>

js

function extend(source, destination) {
    const props = Object.getPrototypeOf(source);
    for(var key in source) {
        destination[key] = source[key];
    }
    Object.getOwnPropertyNames(props).map((key) => {
        if (key !== "constructor") {
            destination[key] = source[key];
        }
    });
}

function AddObserver() {
    const check = document.createElement('input');
    check.type = 'checkBox';
    extend(new Observer(), check);
    check.update = function(value) {
        this.checked = value;
    }
    checkBox.addObserver(check);
    container.appendChild(check);
}
const button = document.getElementsByTagName('button')[0];
const checkBox = document.getElementById('mainCheckBox');
const container = document.getElementById('container');

extend(new Subject(), checkBox);
checkBox.onclick = function() {
    checkBox.notify(checkBox.checked);
}

button.onclick = AddObserver;

demo实际效果可在codepen查看

发布(Publish)/订阅(Subscribe)

我个人理解是观察者模式中的一种更具体的设计,主要区别在于在观察者(Subscriber)和被观察者(Publisher)之间添加了一个主题(Topic)/事件(Event)的通道,该事件系统代码订阅程序的特定事件,这些事件可以传递特定的参数,这些参数就是订阅者响应事件所需要的参数值,其实现解耦了订阅者与发布者的依赖关系。

结构

示例代码(es5 strict)

'use strict';

var pub = {};
(function(p){
    var Event = {};
    var id = 0;
    p.prototype.subscribe = function(eventName, func) {
        if (!Event[eventName]) {
            Event[eventName] = [];
        } 
        var subscriber = {
            name: eventName,
            id: id,
            func: func
        };
        Event[eventName].push(subscriber);
        return subscriber;
    };

    p.prototype.publish = function(eventName, params) {
        var funcCollection = Event[eventName];
        var length = funcCollection && funcCollection.length || 0;
        while(length--) {
            funcCollection[length].func(params);
        }
    }

    p.prototype.unsubscribe = function(event) {
        var subscribers = Event[event.name];
        var length = subscribers.length;
        while (length--) {
            if (subscribes[length].id === event.id) {
                subscribers.splice(length, 1);
            }
        }
    }
})(pub)

results matching ""

    No results matching ""