設計模式之觀察者模式

2022-08-13 06:45:17 字數 3932 閱讀 9434

feb 23, 2015

觀察者模式又叫發布訂閱模式(publish/subscribe),它定義了一種一對多的關係,讓多個觀察者物件同時監聽某乙個主題物件,這個主題物件的狀態發生變化時就會通知所有的觀察者物件,使得它們能夠自動更新自己。

使用觀察者模式的好處:

支援簡單的廣播通訊,自動通知所有已經訂閱過的物件。

頁面載入後目標物件很容易與觀察者存在一種動態關聯,增加了靈活性。

目標物件與觀察者之間的抽象耦合關係能夠單獨擴充套件以及重用。

js 裡對觀察者模式的實現是通過**來實現的,我們來先定義乙個 pubsub 物件,其內部包含了 3 個方法:訂閱、退訂、發布。

var pubsub = {};

(function (q) , // **函式存放的陣列

subuid = -1;

// 發布方法

q.publish = function (topic, args)

settimeout(function ()

}, 0);

return true;

};//訂閱方法

q.subscribe = function (topic, func)

var token = (++subuid).tostring();

topics[topic].push();

return token;

};//退訂方法

q.unsubscribe = function (token) }}

}return false;

};} (pubsub));

使用方式如下:

//來,訂閱乙個

pubsub.subscribe('example1', function (topics, data) );

//發布通知

pubsub.publish('example1', 'hello world!');

pubsub.publish('example1', ['test', 'a', 'b', 'c']);

pubsub.publish('example1', [, ]);

怎麼樣?用起來是不是很爽?但是這種方式有個問題,就是沒辦法退訂訂閱,要退訂的話必須指定退訂的名稱,所以我們再來乙個版本:

//將訂閱賦值給乙個變數,以便退訂

var testsubscription = pubsub.subscribe('example1', function (topics, data) );

//發布通知

pubsub.publish('example1', 'hello world!');

pubsub.publish('example1', ['test', 'a', 'b', 'c']);

pubsub.publish('example1', [, ]);

//退訂

settimeout(function () , 0);

//再發布一次,驗證一下是否還能夠輸出資訊

pubsub.publish('example1', 'hello again! (this will fail)');

我們也可以利用原型的特性實現乙個觀察者模式,**如下:

function observer()

observer.prototype = ,

unsubscribe: function (fn) });

},update: function (o, thisobj) );}

};//測試

var o = new observer;

var f1 = function (data) ;

var f2 = function (data) ;

o.subscribe(f1);

o.subscribe(f2);

o.update("tom回來了!")

//退訂f1

o.unsubscribe(f1);

//再來驗證

o.update("tom回來了!");

如果提示找不到 filter 或者 foreach 函式,可能是因為你的瀏覽器還不夠新,暫時不支援新標準的函式,你可以使用如下方式自己定義:

if (!array.prototype.foreach) };}

if (!array.prototype.filter)

a.push(this[i]);

}return a;};}

如果想讓多個物件都具有觀察者發布訂閱的功能,我們可以定義乙個通用的函式,然後將該函式的功能應用到需要觀察者功能的物件上,**如下:

//通用**

var observer = ,

//退訂

removesubscriber: function (callback) }},

//發布

publish: function (what) }},

// 將物件o具有觀察者功能

make: function (o) }};

然後訂閱 2 個物件 blogger 和 user,使用 observer.make 方法將這 2 個物件具有觀察者功能,**如下:

var blogger =

};var user =

};observer.make(blogger);

observer.make(user);

使用方法就比較簡單了,訂閱不同的**函式,以便可以註冊到不同的觀察者物件裡(也可以同時註冊到多個觀察者物件裡):

var tom =

};var mm =

};// 訂閱

blogger.addsubscriber(tom.read);

blogger.addsubscriber(mm.show);

blogger.recommend(123); //呼叫發布\

//退訂

blogger.removesubscriber(mm.show);

blogger.recommend(456); //呼叫發布

//另外乙個物件的訂閱

user.addsubscriber(mm.show);

user.vote(789); //呼叫發布

根據 jquery1.7 版新增的 on/off 功能,我們也可以定義 jquery 版的觀察者:

(function ($) );

$.subscribe = function () ;

$.unsubscribe = function () ;

$.publish = function () ;

} (jquery));

呼叫方法比上面 3 個版本都簡單:

//**函式

function handle(e, a, b, c) ;

//訂閱

$.subscribe("/some/topic", handle);

//發布

$.publish("/some/topic", ["a", "b", "c"]); // 輸出abc

$.unsubscribe("/some/topic", handle); // 退訂

//訂閱

$.subscribe("/some/topic", function (e, a, b, c) );

$.publish("/some/topic", ["a", "b", "c"]); // 輸出abc

//退訂(退訂使用的是/some/topic名稱,而不是**函式哦,和版本一的例子不一樣

$.unsubscribe("/some/topic");

可以看到,他的訂閱和退訂使用的是字串名稱,而不是**函式名稱,所以即便傳入的是匿名函式,我們也是可以退訂的。

觀察者的使用場合就是:當乙個物件的改變需要同時改變其它物件,並且它不知道具體有多少物件需要改變的時候,就應該考慮使用觀察者模式。

總的來說,觀察者模式所做的工作就是在解耦,讓耦合的雙方都依賴於抽象,而不是依賴於具體。從而使得各自的變化都不會影響到另一邊的變化。

設計模式之觀察者模式

首先說了乙個自己的小例子吧,前兩天我的乙個朋友來找我玩,因為路途比較遠,我需要知道他的位置,然後安排好時間去接他,那麼在這個例子中,我就是乙個觀察者,需要時時刻刻觀察他的位置,我的朋友就是乙個被觀察者。那麼需要知道我朋友的位置,就有兩種方式,第一,我自己打 問,第二,我的朋友告訴我,下面我們來看看這...

設計模式之觀察者模式

一 作用 讓多個觀察者監視某一物件的變化,如果物件變化,則通知所有觀察者。二 例子 抽象主題類 public abstract class subject 移除觀察者 public void detach observer observer 向觀察者 們 發出通知 public void notif...

設計模式之觀察者模式

觀察者模式的定義是 定義物件間的一種一對多的依賴關係。當乙個物件的狀態發生變化時,所有依賴它的物件都會得到通知並自動更新 報社跟讀者的例子 我們用報社和讀者之間的關係來模擬觀察者模式。包含以下主體 報社 news office 讀者介面 reader 具體讀者 reader 二逼青年 reader ...