Ⅰ 什麼是觀察者模式`
觀察者(Observer)模式又名發布-訂閱(Publish/Subscribe)模式。GOF給觀察者模式如下定義:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
在這里先講一下面向對象設計的一個重要原則——單一職責原則。因此系統的每個對象應該將重點放在問題域中的離散抽象上。因此理想的情況下,一個對象只做一件事情。這樣在開發中也就帶來了諸多的好處:提供了重用性和維護性,也是進行重構的良好的基礎。
因此幾乎所有的設計模式都是基於這個基本的設計原則來的。觀察者模式的起源我覺得應該是在GUI和業務數據的處理上,因為現在絕大多數講解觀察者模式的例子都是這一題材。但是觀察者模式的應用決不僅限於此一方面。
下面我們就來看看觀察者模式的組成部分。
1) 抽象目標角色(Subject):目標角色知道它的觀察者,可以有任意多個觀察者觀察同一個目標。並且提供注冊和刪除觀察者對象的介面。目標角色往往由抽象類或者介面來實現。
2) 抽象觀察者角色(Observer):為那些在目標發生改變時需要獲得通知的對象定義一個更新介面。抽象觀察者角色主要由抽象類或者介面來實現。
3) 具體目標角色(Concrete Subject):將有關狀態存入各個Concrete Observer對象。當它的狀態發生改變時, 向它的各個觀察者發出通知。
4) 具體觀察者角色(Concrete Observer):存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer的更新介面以使自身狀態與目標的狀態保持一致。在本角色內也可以維護一個指向Concrete Subject對象的引用。
Ⅱ 在ios中觀察者模式和控制中心在什麼時候使用
什麼是觀察者模式?我們先打個比方,這就像你訂報紙。比如你想知道美國最近放生了些新聞,你可能會訂閱一份美國周刊,然後一旦美國有了新的故事,美國周刊就發一刊,並郵寄給你,當你收到這份報刊,然後你就能夠了解美國最新的動態。其實這就是觀察者模式,A對B的變化感興趣,就注冊為B的觀察者,當B發生變化時通知A,告知B發生了變化。這是一種非常典型的觀察者的用法,我把這種使用方法叫做經典觀察者模式。當然與之相對的還有另外一種觀察者模式——廣義觀察者模式。
從經典的角度看,觀察者模式是一種通知變化的模式,一般認為只在對象發生變化感興趣的場合有用。主題對象知道有觀察者存在,設置會維護觀察者的一個隊列;而從廣義的角度看,觀察者模式是中傳遞變化數據的模式,需要查看對象屬性時就會使用的一種模式,主題對象不知道觀察者的存在,更像是圍觀者。需要知道主題對象的狀態,所以即使在主題對象沒有發生改變的時候,觀察者也可能會去訪問主題對象。換句話說廣義觀察者模式,是在不同的對象之間傳遞數據的一種模式。
觀察者模式應當是在面向對象編程中被大規模使用的設計模式之一。從方法論的角度出發,傳統的認知論認為,世界是由對象組成的,我們通過不停的觀察和了解就能夠了解對象的本質。整個人類的認知模型就是建立在「觀察」這種行為之上的。我們通過不停與世界中的其他對象交互,並觀察之來了解這個世界。同樣,在程序的世界中,我們構建的每一個實例,也是通過不不停的與其他對象交互(查看其他對象的狀態,或者改變其他對象的狀態),並通過觀察其他實例的變化並作出響應,以來完成功能。這也就是,為什麼會把觀察模式單獨提出來,做一個專門的剖析的原因——在我看來他是很多其他設計模式的基礎模式,並且是編程中極其重要的一種設計模式。
經典觀察者模式
經典觀察者模式被認為是對象的行為模式,又叫發布-訂閱(Publish/Subscribe)模式、模型-視圖(Model/View)模式、源-監聽器(Source/Listener)模式或從屬者(Dependents)模式。經典觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己或者做出相應的一些動作。在文章一開始舉的例子就是典型觀察者模式的應用。
而在IOS開發中我們可能會接觸到的經典觀察者模式的實現方式,有這么幾種:NSNotificationCenter、KVO、Delegate等
感知通知方式
在經典觀察者模式中,因為觀察者感知到主題對象變化方式的不同,又分為推模型和拉模型兩種方式。
推模型
ios desing pattern observer 1
主題對象向觀察者推送主題的詳細信息,不管觀察者是否需要,推送的信息通常是主題對象的全部或者部分數據。推模型實現了觀察者和主題對象的解耦,兩者之間沒有過度的依賴關系。但是推模型每次都會以廣播的方式,向所有觀察者發送通知。所有觀察者被動的接受通知。當通知的內容過多時,多個觀察者同時接收,可能會對網路、內存(有些時候還會涉及IO)有較大影響。
在IOS中典型的推模型實現方式為NSNotificationCenter和KVO。
NSNotificationCenter
NSnotificationCenter是一種典型的有調度中心的觀察者模式實現方式。以NSNotificationCenter為中心,觀察者往Center中注冊對某個主題對象的變化感興趣,主題對象通過NSNotificationCenter進行變化廣播。這種模型就是文章開始發布訂閱報紙在OC中的一種類似實現。所有的觀察和監聽行為都向同一個中心注冊,所有對象的變化也都通過同一個中心向外廣播。
SNotificationCenter就像一個樞紐一樣,處在整個觀察者模式的核心位置,調度著消息在觀察者和監聽者之間傳遞。
ios desing pattern observer 2
一次完整的觀察過程如上圖所示。整個過程中,關鍵的類有這么幾個(介紹順序按照完成順序):
觀察者Observer,一般繼承自NSObject,通過NSNotificationCenter的addObserver:selector:name:object介面來注冊對某一類型通知感興趣.在注冊時候一定要注意,NSNotificationCenter不會對觀察者進行引用計數+1的操作,我們在程序中釋放觀察者的時候,一定要去報從center中將其注銷了。
- (void) handleMessage:(NSNotification*)nc{
//解析消息內容
NSDictionary* userInfo = [nc userInfo];
}
- (void) commonInit
{
//注冊觀察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleMessage:) name:kDZTestNotificatonMessage object:nil];
}
通知中心NSNotificationCenter,通知的樞紐。
主題對象,被觀察的對象,通過postNotificationName:object:userInfo:發送某一類型通知,廣播改變。
- (void) postMessage
{
[[NSNotificationCenter defaultCenter] postNotificationName:kDZTestNotificatonMessage object:Nil userInfo:@{}];
}
通知對象NSNotification,當有通知來的時候,Center會調用觀察者注冊的介面來廣播通知,同時傳遞存儲著更改內容的NSNotification對象。
apple版實現的NotificationCenter讓我用起來不太爽的幾個小問題
在使用NSNotificationCenter的時候,從編程的角度來講我們往往不止是希望能夠做到功能實現,還能希望編碼效率和整個工程的可維護性良好。而Apple提供的以NSNotificationCenter為中心的觀察者模式實現,在可維護性和效率上存在以下缺點:
每個注冊的地方需要同時注冊一個函數,這將會帶來大量的編碼工作。仔細分析能夠發現,其實我們每個觀察者每次注冊的函數幾乎都是雷同的。這就是種變相的CtrlCV,是典型的醜陋和難維護的代碼。
每個觀察者的回調函數,都需要對主題對象發送來的消息進行解包的操作。從UserInfo中通過KeyValue的方式,將消息解析出來,而後進行操作。試想一下,工程中有100個地方,同時對前面中在響應變化的函數中進行了解包的操作。而後期需求變化需要多傳一個內容的時候,將會是一場維護上的災難。
當大規模使用觀察者模式的時候,我們往往在dealloc處加上一句:
[[NSNotificationCenter defaultCenter] removeObserver:self]
而在實際使用過程中,會發現該函數的性能是比較低下的。在整個啟動過程中,進行了10000次RemoveObserver操作,
@implementation DZMessage
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
....
for (int i = 0 ; i < 10000; i++) {
DZMessage* message = [DZMessage new];
}
通過下圖可以看出這一過程消耗了23.4%的CPU,說明這一函數的效率還是很低的。
ios desing pattern observer 6
這還是只有一種消息類型的存在下有這樣的結果,如果整個NotificationCenter中混雜著多種消息類型,那麼恐怕對於性能來說將會是災難性的。
for (int i = 0 ; i < 10000; i++) {
DZMessage* message = [DZMessage new];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handle) name:[@(i) stringValue] object:nil];
}
增加了多種消息類型之後,RemoveObserver佔用了啟動過程中63.9%的CPU消耗。
ios desing pattern observer 7
而由於Apple沒有提供Center的源碼,所以修改這個Center幾乎不可能了。
改進版的有中心觀察者模式(DZNotificationCenter)
GitHub地址�0�2在設計的時候考慮到以上用起來不爽的地方,進行了優化:
將解包到執行函數的操作進行了封裝,只需要提供某消息類型的解包block和消息類型對應的protocol,當有消息到達的時候,消息中心會進行統一解包,並直接調用觀察者相應的函數。
對觀察者的維護機制進行優化(還未做完),提升查找和刪除觀察者的效率。
DZNotificationCenter的用法和NSNotificationCenter在注冊和注銷觀察者的地方是一樣的,不一樣的地方在於,你在使用的時候需要提供解析消息的block。你可以通過兩種方式來提供。
直接注冊的方式
[DZDefaultNotificationCenter addDecodeNotificationBlock:^SEL(NSDictionary *userInfo, NSMutableArray *__autoreleasing *params) {
NSString* key = userInfo[@"key"];
if (params != NULL) {
*params = [NSMutableArray new];
}
[*params addObject:key];
return @selector(handleTestMessageWithKey:);
} forMessage:kDZMessageTest];
實現DZNotificationInitDelegaete協議,當整個工程中大規模使用觀察者的時候,建議使用該方式。這樣有利於統一管理所有的解析方式。
- (DZDecodeNotificationBlock) decodeNotification:(NSString *)message forCenter:(DZNotificationCenter *)center
{
if (message == kDZMessageTest) {
return ^(NSDictionary* userInfo, NSMutableArray* __autoreleasing* params){
NSString* key = userInfo[@"key"];
if (params != NULL) {
*params = [NSMutableArray new];
}
[*params addObject:key];
return @selector(handlePortMessage:);
};
}
return nil;
}
在使用的過程中為了,能夠保證在觀察者處能夠回調相同的函數,可以實現針對某一消息類型的protocol
@protocol DZTestMessageInterface <NSObject>
- (void) handleTestMessageWithKey:(NSString*)key;
@end
這樣就能夠保證,在使用觀察者的地方不用反復的拼函數名和解析消息內容了。
@interface DZViewController () <DZTestMessageInterface>
@end
@implementation DZViewController
....
- (void) handleTestMessageWithKey:(NSString *)key
{
self.showLabel.text = [NSString stringWithFormat:@"get message with %@", key];
}
....
KVO
KVO的全稱是Key-Value Observer,即鍵值觀察。是一種沒有中心樞紐的觀察者模式的實現方式。一個主題對象管理所有依賴於它的觀察者對象,並且在自身狀態發生改變的時候主動通知觀察者對象。 讓我們先看一個完整的示例:
static NSString* const kKVOPathKey = @"key";
@implementation DZKVOTest
- (void) setMessage:(DZMessage *)message
{
if (message != _message) {
if (_message) {
[_message removeObserver:self forKeyPath:kKVOPathKey];
}
if (message) {
[message addObserver:self forKeyPath:kKVOPathKey options:NSKeyValueObservingOptionNew context:Nil];
}
_message = message;
}
}
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqual:kKVOPathKey] && object == _message) {
NSLog(@"get %@",change);
}
}
- (void) postMessage
{
_message.key = @"asdfasd";
}
@end
Ⅲ 什麼是觀察者模式(Observer)
觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,讓他們能夠自動更新自己 觀察者模式的組成 抽象主題角色:把所有對觀察者對象的引用保存在一個集合中,每個抽象主題角色都可以有任意數量的觀察者。抽象主題提供一個介面,可以增加和刪除觀察者角色。一般用一個抽象類或介面來實現。 抽象觀察者角色:為所有具體的觀察者定義一個介面,在得到主題的通知時更新自己。 從AWT1.1開始圖形系統的事件模型採用觀察者模式,因此觀察者模式在Java語言中的地位極其重要 在xml解析中的SAX也採用了觀察者模式來實現 Java也提供了對觀察者模式的內置支持 Observable類用於創建可以觀測到你的程序中其他部分的子類。當這種子類的對象發生變化時,觀測類被通知。觀測類必須實現定義了update(
Ⅳ Java設計模式求助(命令模式)
先說一下命令模式,舉一個例子說明一下,玉帝傳美猴王上天,玉帝創建了一個命令就是聖旨,然後指出聖旨的接受者美猴王,而太白金星只是傳達命令的人。這個過程就是命令模式的應用。
這個好處就是玉帝將不會直接和美猴王打交道,他只需把命令封裝在聖旨中交給太白金星傳達即可其他的事他就不用問了。
下面再來解釋一下觀察者模式,還以西遊記為例,唐三藏被紅孩兒所困,孫悟空為救他去求菩薩,而菩薩聽後將自己的寶珠凈瓶向海中一摜,只見一隻烏龜馱了一隻瓶子上來。。。。這個烏龜就是觀察者,被觀察的對象就是菩薩,這裡面就可以看出命令模式與之區別,烏龜是等待觀察菩薩的動作,而玉帝是自己發出命令。這裡面有時候很會亂的,觀察者看的是烏龜怎麼來實現,而命令是看發命令的人怎麼安排的。。。。
說的不好,請多諒解!
Ⅳ 觀察者模式是什麼
官方解釋:
觀察者模式(有時又被稱為發布-訂閱Subscribe>模式、模型-視圖View>模式、源-收聽者Listener>模式或從屬者模式)是軟體設計模式的一種。在此種模式中,一個目標物件管理所有相依於它的觀察者物件,並且在它本身的狀態改變時主動發出通知。這通常透過呼叫各觀察者所提供的方法來實現。此種模式通常被用來實作事件處理系統。
個人理解:
觀察者模式是一種思想,不需要人為的去關注觀察者和被觀察者之間是怎樣聯系的,實現了解耦,只需要對象去注冊被觀察者(Observerable)與觀察者(Observer),然後被觀察者去添加一個或者多個觀察者,當被觀察者發生變動就會立即通知所有的觀察者,下面讓我們來看看是怎樣實現這個功能的。
被觀察者首先通過addObserver(Observer o)來添加一個觀察者,底層代碼中會把這個對象o放進一個vector集合中,當然也可以添加多個觀察者,當觀察者發生變動的時候就會觸發
setChanged();
notifyObservers();
這兩個方法,然後底層代碼中就回去遍歷裝有觀察者的那個vector,然後
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
調用update方法通知每一個觀察者,這樣觀察者對象中就可以拿到被觀察者的相關對象和信息
Ⅵ java中什麼叫"觀察者設計模式"
才開始學習Java沒有多久,看過了不少基礎類的書籍,正嘗試著做一些基礎性的項目來整合零散的知識點。偶然之下在網上查資料時看到別人文章里提及"觀察者設計模式",突然很詫異,沒有聽說過這種模式呢~故而在網上搜集了一些資料又在圖書館找了一下相關書籍來學習。突然覺得也來學學他人,做做筆記吧~例如:現在很多的購房者都在關注房子的價格變化,每當房子價格變化時,所有 購房者都可以觀察得到,實際上以上的購房者都屬於觀察者,他們都在關注著房子的價格。。其實這就叫觀察者設計模式。由java.util包中提供的Observable類和Observer介面便可以輕松實現觀察者模式,需要被觀察的類必須繼承Observable類。Observable類的常用方法有:public void addObserver(Observer o) ; public void deleteObserver(Observero); public void update(Observable o,Object arg);protected void setChanged(); //被觀察者狀態發生改變public void notifyObservers(Object arg) //通知所有觀察者狀態已改變對觀察者模式的第一感覺是,實現此模式應該可以大大簡化代碼,使相關功能的代碼塊語義更清晰. 具體還得在以後應用中慢慢體悟下附一個觀察者模式的實現:package org.lxh.demoll.obserdemo;import java.util.Observable;
import java.util.Observer;
class House extends Observable{
private float price;
public House(float price){
this.price = price;
}
public void setPrice(float price){
super.setChanged();
super.notifyObservers(price);
this.price=price;
}
public String toString(){
return "房子價格為:" + this.price;
}
}
class HousePriceObserver implements Observer{
private String name;
public HousePriceObserver(String name){
this.name = name;
}
public void update(Observable obj,Object arg){
if(arg instanceof Float){
System.out.println(this.name+"觀察到價格是否更改為:");
System.out.println(((Float) arg).floatValue());
}
}
}
public class ObserDemo01{
public static void main(String[] args){
House h = new House(1000000);
HousePriceObserver hpo1 = new HousePriceObserver("購房者A");
HousePriceObserver hpo2 = new HousePriceObserver("購房者B");
HousePriceObserver hpo3 = new HousePriceObserver("購房者C");
h.addObserver(hpo1);
h.addObserver(hpo2);
h.addObserver(hpo3);
System.out.println(h);
h.setPrice(666666);
System.out.println(h);
}
}
Ⅶ 觀察者模式和發布/訂閱模式的區別
觀察者(Observer)模式又名發布-訂閱(Publish/Subscribe)模式。GOF給觀察者模式如下定義:定義對象間的一種一對多的依賴關系,當一個對象的狀態發生改變時,所有依賴於它的對象都得到通知並被自動更新。
在這里先講一下面向對象設計的一個重要原則——單一職責原則。因此系統的每個對象應該將重點放在問題域中的離散抽象上。因此理想的情況下,一個對象只做一件事情。這樣在開發中也就帶來了諸多的好處:提供了重用性和維護性,也是進行重構的良好的基礎。
因此幾乎所有的設計模式都是基於這個基本的設計原則來的。觀察者模式的起源我覺得應該是在GUI和業務數據的處理上,因為現在絕大多數講解觀察者模式的例子都是這一題材。但是觀察者模式的應用決不僅限於此一方面。
下面我們就來看看觀察者模式的組成部分。
1) 抽象目標角色(Subject):目標角色知道它的觀察者,可以有任意多個觀察者觀察同一個目標。並且提供注冊和刪除觀察者對象的介面。目標角色往往由抽象類或者介面來實現。
2) 抽象觀察者角色(Observer):為那些在目標發生改變時需要獲得通知的對象定義一個更新介面。抽象觀察者角色主要由抽象類或者介面來實現。
3) 具體目標角色(Concrete Subject):將有關狀態存入各個Concrete Observer對象。當它的狀態發生改變時, 向它的各個觀察者發出通知。
4) 具體觀察者角色(Concrete Observer):存儲有關狀態,這些狀態應與目標的狀態保持一致。實現Observer的更新介面以使自身狀態與目標的狀態保持一致。在本角色內也可以維護一個指向Concrete Subject對象的引用。
Ⅷ 觀察者模式的基本簡介
觀察者模式(Observer)完美的將觀察者和被觀察的對象分離開。舉個例子,用戶界面可以作為一個觀察者,業務數據是被觀察者,用戶界面觀察業務數據的變化,發現數據變化後,就顯示在界面上。面向對象設計的一個原則是:系統中的每個類將重點放在某一個功能上,而不是其他方面。一個對象只做一件事情,並且將他做好。觀察者模式在模塊之間劃定了清晰的界限,提高了應用程序的可維護性和重用性。
觀察者設計模式定義了對象間的一種一對多的依賴關系,以便一個對象的狀態發生變化時,所有依賴於它的對象都得到通知並自動刷新。
Ⅸ 誰給我解釋下啥叫做觀察者模式
官方的定義:
The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically. (觀察者模式定義了對象間的一種一對多依賴關系,使得每當一個對象改變狀態,則所有依賴於它的對象都會得到通知並被自動更新)
Ⅹ python中觀察者模式的作用
在現實國際中,許多方針並不是獨立存在的,其間一個方針的行為產生改動可能會導致一個或許多個其他方針的行為也產生改動。
這樣的例子還有許多,例如小偷與警察,貓和老鼠等
觀察者形式就如一個聊天室,當你需要收到聊天室的音訊時,你就注冊成為聊天室的成員,當聊天室有信息更新時,就會傳到你那去。當你不需要接收聊天室的信息時,能夠注銷掉,退出聊天室。
2.形式的界說與特點
降低了方針與觀察者之間的耦合聯系,兩者之間是抽象耦合聯系。
方針與觀察者之間建立了一套觸發機制。
4.它的主要缺陷如下
經過前面的分析與應用實例可知觀察者形式適合以下幾種情形。<ol font-size:14px;background-color:#faf7ef;"="" style="font-family: "sans serif", tahoma, verdana, helvetica; font-size: 12px; white-space: normal; color: rgb(57, 57, 57);">
方針間存在一對多聯系,一個方針的狀況產生改動會影響其他方針。
當一個抽象模型有兩個方面,其間一個方面依靠於另一方面時,可將這二者封裝在獨立的方針中以使它們能夠各自獨立地改動和復用。