javaScript 設計模式系列之一:觀察者模式
介紹
觀察者模式又叫發布訂閱模式(Publish/Subscribe),一個目標對象管理所有相依於它的觀察者對象。該模式中存在兩個角色:觀察者和被觀察者。目標對象與觀察者之間的抽象耦合關係能夠單獨擴展以及重用。
該模式通常有兩種實現策略:"推"(push) 和 "拉"(pull)
例:對於報社可能僱傭投送人員四處送報給訂閱者,這就是主動推送。而對於規模小的報社沒有足夠的資源去僱傭投送員,這時候可以採取 "拉" 的方式。就是在訂閱者附近提供自己的數據,供訂閱者 "拉" 自己所需的數據。
實現push
var Observable = {
observers:
, lastId: -1
, addObserver: function(observer) {
this.observers.push({
callback: observer
, id: ++this.lastId
})
return this.lastId
}
, removeObserver: function(id) {
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i]
if (this.observers[i].id == id) {
this.observers.splice(i, 1)
return true
}
}
return false
}
, notifyObservers: function(message) {
for (var i = this.observers.length - 1; i >= 0; i--) {
this.observers[i].callback(message)
};
}
}
var id_1 = Observable.addObserver(function(message){
console.log("First observer message:" + message)
})
var observer = function(message){
console.log("Second observer message:" + message)
}
var id_2 = Observable.addObserver(observer)
Observable.notifyObservers("test 1")
Observable.removeObserver(id_2)
Observable.notifyObservers("test 2")
pull
var Observable = {}
;(function(O){
var observers =
, privateVar
O.addObserver = function(observer) {
observers.push(observer)
}
O.removeObserver = function(observer) {
var index = observers.indexOf(observer)
if (~index) {
observers.splice(index, 1)
}
}
O.notifyObservers = function {
for (var i = observers.length - 1; i >= 0; i--) {
observers[i].update
};
}
O.updatePrivate = function(newValue) {
privateVar = newValue
this.notifyObservers
}
O.getPrivate = function {
return privateVar
}
}(Observable))
Observable.addObserver({
update: function{
this.process
}
, process: function{
var value = Observable.getPrivate
console.log("Private value is: " + value)
}
})
Observable.updatePrivate("test 1")
// Private value is: test 1
Observable.updatePrivate("test 2")
// Private value is: test 2
被觀察對象將通知所有的觀察者,並且每個觀察者將從被觀察對象中提取所需的信息。
讓多個對象都具有觀察者發布訂閱的功能
var observer = {
addSubscriber:function (callback) {
this.subscribers[this.subscribers.length] = callback;
},
removeSubscriber:function (callback) {
for (var i = 0; i < this.subscribers.length; i++) {
if (this.subscribers[i] === callback) {
delete(this.subscribers[i]);
}
}
},
publish:function (what) {
for (var i = 0; i < this.subscribers.length; i++) {
if (typeof this.subscribers[i] === "function") {
this.subscribers[i](what);
}
}
},
make:function (o) { // turns an object into a publisher
for (var i in this) {
o[i] = this[i];
o.subscribers = ;
}
}
};
var blogger = {
writeBlogPost:function {
var content = "Today is " + new Date;
this.publish(content);
}
};
var la_times = {
newIssue:function {
var paper = "Martians have landed on Earth!";
this.publish(paper);
}
};
observer.make(blogger);
observer.make(la_times);
var jack = {
read:function (what) {
console.log("I just read that " + what)
}
};
var jill = {
gossip:function (what) {
console.log("You didn"t hear it from me, but " + what)
}
};
blogger.addSubscriber(jack.read);
blogger.addSubscriber(jill.gossip);
blogger.writeBlogPost;
blogger.removeSubscriber(jill.gossip);
blogger.writeBlogPost;
la_times.addSubscriber(jill.gossip);
la_times.newIssue;
避免創建多個被觀察者對象,可以增加 "命名空間"
var Observable = {
observers:
, addObserver: function(topic, observer) {
this.observers[topic] || (this.observers[topic] = [])
this.observers[topic].push(observer)
}
, removeObserver: function(topic, observer) {
if (!this.observers[topic])
return;
var index = this.observers[topic].indexOf(observer)
if (~index) {
this.observers[topic].splice(index, 1)
}
}
, notifyObservers: function(topic, message) {
if (!this.observers[topic])
return;
for (var i = this.observers[topic].length - 1; i >= 0; i--) {
this.observers[topic][i](message)
};
}
}
Observable.addObserver("cart", function(message){
console.log("First observer message:" + message)
})
Observable.addObserver("notificatons", function(message){
console.log("Second observer message:" + message)
})
Observable.notifyObservers("cart", "test 1")
// First observer message:test 1
Observable.notifyObservers("notificatons", "test 2")
// Second observer message:test 2
相關閱讀
※Swift 中 String 取下標及性能問題
※.Net Core中使用ref和Span
※每天一道Java題「4」
※MySQL 的性能(上篇)——SQL 執行時間分析
※linux c++爬蟲(一)
TAG:科技優家 |
※「設計模式專題」Singleton
※static 單例模式autoptr與單例模式const 用法小結mutable修飾符
※web api之selfhost模式
※刨銑acessemarketing商業模式
※Ghost Recon Wildlands更新將使用Permadeath 模式
※iOS 12 beta 5 開發者測試版暗示「iPhone X Plus」將有 iPad 的橫屏模式
※Google Assistant登陸iPad平板:支持多任務模式
※《Avengers: Infinity War》將與《Fortnite》推出聯乘模式
※微軟Outlook.com beta上線暗黑模式
※Flutter 的編譯模式
※谷歌AR Sticker改為Playground,作為Pixel相機新模式
※Chrome OS多屏模式下更像Windows
※Android P Beta 3「暗黑模式」改進
※任天堂Switch豎向掌機模式配件上架kickstarter眾籌平台
※Zynga的《CSR Racing 2》AR模式進入Android設備
※雙HomePod立體聲模式叫做FullRoom
※像Mac一樣裝Win 10!Pixelbook驚現雙系統模式
※新技能Get!Bosesoundlinkrevolve+的派對模式怎麼玩才過癮?
※哄搶模式開啟!Virgil Abloh x Air Jordan 1發售信息官方確認!
※網路專家解讀YouTube,Twitter或Reddit的盈利模式