觀察者模式模式簡介
觀察者模式(又被稱爲發佈-訂閱(Publish/Subscribe)模式,屬於行爲型模式的一種,它定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態變化時,會通知全部的觀察者對象,使他們可以自動更新本身。
觀察者模式機動
創建一種對象與對象之間的依賴關係,一個對象發生改變時將自動通知其餘對象,其餘對象將相應作出反應。在此,發生改變的對象稱爲觀察目標,而被通知的對象稱爲觀察者,一個觀察目標能夠對應多個觀察者,並且這些觀察者之間沒有相互聯繫,能夠根據須要增長和刪除觀察者,使得系統更易於擴展,這就是觀察者模式的模式動機。
生活中的觀察者模式
如今年輕人都喜歡玩手機,好比我本身我是比較愛看直播,每一個直播間都有一個訂閱的按鈕,若是你喜歡這個直播你就會訂閱一下它,可是每一個主播開播的時間是不固定的,咱們不能一直盯着直播間看吧,這樣很浪費時間也錯過了其餘的內容,因此你訂閱它以後,每一個主播開播都會向本身訂閱的號發佈本身開播的消息
代碼分析
- 咱們使用Es6先建立一個class
// 發佈訂閱實現
class Observer {
constructor () {
}
}
- 訂閱(subscribe)的函數callback參數用做傳入的訂閱者回調函數,this.subscribers.length插入當前本身應當的位置
subscribe (callback) {
// 將傳入的函數賦予這個數組
this.subscribers[this.subscribers.length] = callback
}
- 退訂(retreatSubscribe)函數,傳入退訂者的回調函數,循環存儲訂閱者的數組this.subscribers,根據傳入的退訂者和訂閱者數組中對比,相同者刪除訂閱者
retreatSubscribe (callback) {
for(var i = 0;i < this.subscribers.length;i++) {
if(this.subscribers[i] === callback){
delete (this.subscribers[i])
}
}
}
- 觀察(publish)函數,觀察訂閱者的動做,this指向的是這個class Observer,將Observer內的函數方法賦予訂閱者對象,聲明數組用做存儲訂閱者回調函數
make (o) {
// this === Observer這個對象的函數
for(var i in this){
// this[i]Observer對象裏面的每一個方法
o[i] = this[i]
// 聲明數組用做存儲訂閱者回調函數
o.subscribers = []
}
}
- 發佈(publish)函數,循環存儲訂閱者回調函數的數組,檢測是否爲函數,若是是函數進行發佈消息
//發佈
publish (what) {
for(var i = 0;i< this.subscribers.length;i++){
if(typeof this.subscribers[i] === 'function'){
// add函數
this.subscribers[i](what)
}
}
}
代碼組合起來
下面的class代碼是我將上面步驟的組合到一塊兒的一系列代碼,由訂閱對象,觀察對象,發佈消息,退訂組成的觀察者模式,也叫發佈訂閱
class Observer {
constructor () {}
// 訂閱
subscribe (callback) {
// 將傳入的函數賦予這個數組
this.subscribers[this.subscribers.length] = callback
}
// 退訂
retreatSubscribe (callback) {
for(var i = 0;i < this.subscribers.length;i++) {
if(this.subscribers[i] === callback){
delete (this.subscribers[i])
}
}
}
// 觀察對象
make (o) {
// this === Observer這個對象的函數
for(var i in this){
// this[i]Observer對象裏面的每一個方法
o[i] = this[i]
// 聲明數組用做存儲訂閱者回調函數
o.subscribers = []
}
}
// 發佈
publish (what) {
for(var i = 0;i< this.subscribers.length;i++){
if(typeof this.subscribers[i] === 'function'){
// add函數
this.subscribers[i](what)
}
}
}
}
使用上面的觀察者
1.咱們必須建立一個訂閱者對象
let people = {
}
2.咱們觀察這個對象而且賦值給這個對象可使用的功能,咱們讓他能夠行動,能夠作出行爲舉止
Observer.make(people)
3.聲明想發佈的信息代碼
let wanglei = {
add (what) {
console.log('wanglei給' + what);
}
}
4.咱們訂閱一下想要發送的函數,咱們這裏正好是聲明的函數,用來訂閱用的,能夠回顧上面訂閱的函數代碼
Observer.subscribe(wanglei.add)
5.發佈消息咱們將qaaa字符傳遞到add訂閱函數的what形參裏面用來組合發送消息
Observer.publish('qaaa')
//打印
wanglei給qaaa
6.退訂既然能夠訂閱,咱們就能夠退訂,退訂主要走的retreatSubscribe函數,咱們將訂閱者的信息傳遞到退訂函數就能夠刪除這個訂閱者,以後再發布就沒法再接收到相關信息
Observer.retreatSubscribe(wang.add)
觀察者優缺點
那麼使用完觀察者以後大家有什麼感觸,總的來講觀察者有優勢也有缺點,每一個事物都同樣總會有優缺點,可是觀察者的優勢在咱們部分功能中起到不少做用,咱們看看它的優缺點
優勢:
1. 支持簡單的廣播通訊,自動通知全部已經訂閱過的對象
2. 目標對象與觀察者存在的是動態關聯,增長了靈活性
3. 目標對象與觀察者之間的抽象耦合關係可以單獨擴展以及重用
缺點:
1. 若是一個觀察目標對象有不少直接和間接的觀察者的話,將全部的觀察者都通知到會花費不少時間
2. 若是在觀察者和觀察目標之間有循環依賴的話,觀察目標會觸發它們之間進行循環調用,可能致使系統崩潰
3. 觀察者模式沒有相應的機制讓觀察者知道所觀察的目標對象是怎麼發生變化的,而僅僅只是知道觀察目標發生了變化
最後咱們的觀察者就到這裏了