JS Pattern - Observer
Updated at 2015-05-13 13:08
var Subject = (function() {
'use strict';
/**
* Allows mixed object to notify linked observers.
* @constructor
*/
var Subject = function() {
this.observers = [];
};
Subject.mixinTo = function(target) {
var source = new Subject();
for (var key in source) {
target[key] = source[key];
}
};
Subject.prototype.addObserver = function(observer) {
this.observers.push(observer);
};
Subject.prototype.removeObserver = function(observer) {
var i = this.observers.length;
while (i--) {
if (this.observers[i] === observer) {
this.observers.splice(i, 1);
}
}
return null;
};
Subject.prototype.notifyObservers = function(context) {
context = context || {};
var observerCount = this.observers.length;
for (var i = 0; i < observerCount; i++) {
this.observers[i].onNotify(context);
}
};
Subject.prototype.getObserverAt = function(index) {
var v = this.observers[index];
return (v === void 0) ? null : v;
};
Subject.prototype.getObserverCount = function() {
return this.observers.length;
};
Subject.prototype.removeAllObservers = function() {
this.observers = [];
};
return Subject;
}());
var Observer = (function() {
'use strict';
/**
* Allows mixed object to listen notifications made by linked subjects.
* @constructor
*/
var Observer = function(options) {
options = options || {onNotify: function() {}};
this.onNotify = options.onNotify;
};
Observer.mixinTo = function(target, onNotify) {
var source = new Observer({onNotify: onNotify});
for (var key in source) {
target[key] = source[key];
}
};
return Observer;
}());
var mySubject = {};
Subject.mixinTo(mySubject);
var check = {};
Observer.mixinTo(check, function(context) {
console.log('check: ' + context.msg);
});
var done = {};
Observer.mixinTo(done, function(context) {
console.log('done: ' + context.msg);
});
console.assert(mySubject.getObserverCount() === 0);
mySubject.addObserver(check);
console.assert(mySubject.getObserverCount() === 1);
mySubject.addObserver(done);
console.assert(mySubject.getObserverCount() === 2);
console.assert(mySubject.getObserverAt(3) === null);
mySubject.notifyObservers({msg: '1'});
mySubject.removeObserver(check);
console.assert(mySubject.getObserverCount() === 1);
mySubject.notifyObservers({msg: '2'});
mySubject.addObserver(check);
console.assert(mySubject.getObserverAt(0) === done);
mySubject.removeAllObservers();
console.assert(mySubject.getObserverCount() === 0);
mySubject.notifyObservers({msg: '3'});
console.assert(mySubject.getObserverAt(0) === null);