オブザーバモードとパブリッシュ/サブスクリプションモード
7998 ワード
オブザーバモードとパブリッシュ/サブスクリプションモード
オブザーバモード
コンセプト
1つの被観察者のオブジェクトは、登録によって1組の観察者オブジェクトを維持する.被観察者が変化すると,通知が生成され,ブロードキャストにより送信され,最後に各観察者の更新方法が呼び出される.観察者が被観察者の通知を受け入れる必要がなくなった場合、被観察者は、その観察者を維持されたグループから削除することができる.
インプリメンテーション
このインプリメンテーションには、次のコンポーネントが含まれます.
function ObserverList() {
this.observerList = []
}
ObserverList.prototype.add = function(obj) {
return this.observerList.push(obj)
}
ObserverList.prototype.Empty = function() {
this.observerList = []
}
ObserverList.prototype.removeAt = function(index) {
this.observerList.splice(index, 1)
}
ObserverList.prototype.count = function() {
return this.observerList.length
}
ObserverList.prototype.get = function(index) {
if (index > -1 && index < this.observerList.length) {
return this.observerList[index]
}
}
// Extend an object with an extension
function extend(extension, obj) {
for (var key in extension) {
obj[key] = extension[key]
}
}
function Subject() {
this.observers = new ObserverList()
}
Subject.prototype.addObserver = function(observer) {
this.observers.add(observer)
}
Subject.prototype.removeObserver = function(observer) {
this.observers.removeAt(this.observers.IndexOf(observer, 0))
}
Subject.prototype.notify = function(context) {
var observerCount = this.observers.count()
for (var i = 0; i < observerCount; i++) {
this.observers.get(i).update(context)
}
}
function Observer() {
this.update = function() {
// ...
}
}
サンプル適用
上のオブザーバーコンポーネントを使用して定義します
// DOM
var controlCheckbox = document.getElementById('mainCheckbox'),
addBtn = document.getElementById('addNewObserver'),
container = document.getElementById('observersContainer')
//
// Subject controlCheckbox
extend(new Subject(), controlCheckbox)
// checkbox
controlCheckbox['onclick'] = new Function(
'controlCheckbox.notify(controlCheckbox.checked)'
)
addBtn['onclick'] = AddNewObserver
//
function AddNewObserver() {
// checkbox
var check = document.createElement('input')
check.type = 'checkbox'
// Observer checkbox
extend(new Observer(), check)
// update
check.update = function(value) {
this.checked = value
}
//
controlCheckbox.AddObserver(check)
//
container.appendChild(check)
}
上記の例では
パブリッシュ/サブスクリプションモード
インプリメンテーション
var pubsub = {}
;(function(q) {
var topics = {},
subUid = -1
// Publish or broadcast events of interest
// with a specific topic name and arguments
// such as the data to pass along
q.publish = function(topic, args) {
if (!topics[topic]) {
return false
}
var subscribers = topics[topic],
len = subscribers ? subscribers.length : 0
while (len--) {
subscribers[len].func(topic, args)
}
return this
}
// Subscribe to events of interest
// with a specific topic name and a
// callback function, to be executed
// when the topic/event is observed
q.subscribe = function(topic, func) {
if (!topics[topic]) {
topics[topic] = []
}
var token = (++subUid).toString()
topics[topic].push({
token: token,
func: func
})
return token
}
// Unsubscribe from a specific
// topic, based on a tokenized reference
// to the subscription
q.unsubscribe = function(token) {
for (var m in topics) {
if (topics[m]) {
for (var i = 0, j = topics[m].length; i < j; i++) {
if (topics[m][i].token === token) {
topics[m].splice(i, 1)
return token
}
}
}
}
return this
}
})(pubsub)
サンプル適用1
// Another simple message handler
// A simple message logger that logs any topics and data received through our
// subscriber
var messageLogger = function(topics, data) {
console.log('Logging: ' + topics + ': ' + data)
}
// Subscribers listen for topics they have subscribed to and
// invoke a callback function (e.g messageLogger) once a new
// notification is broadcast on that topic
var subscription = pubsub.subscribe('inbox/newMessage', messageLogger)
// Publishers are in charge of publishing topics or notifications of
// interest to the application. e.g:
pubsub.publish('inbox/newMessage', 'hello world!')
// or
pubsub.publish('inbox/newMessage', ['test', 'a', 'b', 'c'])
// or
pubsub.publish('inbox/newMessage', {
sender: '[email protected]',
body: 'Hey again!'
})
// We cab also unsubscribe if we no longer wish for our subscribers
// to be notified
// pubsub.unsubscribe( subscription );
// Once unsubscribed, this for example won't result in our
// messageLogger being executed as the subscriber is
// no longer listening
pubsub.publish('inbox/newMessage', 'Hello! are you still there?')
サンプル適用2
古いコード
$.ajax('http:// xxx.com?login', function(data) {
header.setAvatar(data.avatar) // header
nav.setAvatar(data.avatar) //
})
パブリケーション/サブスクリプションモードを使用したコード
$.ajax('http:// xxx.com?login', function(data) {
pubsub.publish('loginSucc', data) //
})
// header
var header = (function() {
pubsub.subscribe('loginSucc', function(data) {
header.setAvatar(data.avatar)
})
return {
setAvatar: function(data) {
console.log(' header ')
}
}
})()
// nav
var nav = (function() {
pubsub.subscribe('loginSucc', function(data) {
nav.setAvatar(data.avatar)
})
return {
setAvatar: function(avatar) {
console.log(' nav ')
}
}
})()
メリット
欠点
両者の相違
controlCheckbox.AddObserver(check)