第九章 行為模式2觀察者模式_第1頁
第九章 行為模式2觀察者模式_第2頁
第九章 行為模式2觀察者模式_第3頁
第九章 行為模式2觀察者模式_第4頁
第九章 行為模式2觀察者模式_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

OBSERVER(觀察者)-對象行為型模式1.意圖定義對象間的一種一對多的依賴關(guān)系,當一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并被自動更新。2.別名依賴(Dependents),發(fā)布-訂閱(Publis-Subscribe)3.動機當前環(huán)境中有如圖所示的三個不同的顯示項。用戶也可以獲取天氣狀態(tài)和預(yù)報。

我們需要創(chuàng)建一個應(yīng)用程序,可以根據(jù)天氣數(shù)據(jù)對象來更新當前狀況、氣象統(tǒng)計以及天氣預(yù)報的三個布告板。

這三個方法分別返回最近的天氣測量值,包括氣溫、濕度和氣壓值。我們不必關(guān)心這些變量是怎么設(shè)置的,對象WeatherData知道如何從氣象站獲取更新的信息。我們的工作是,實現(xiàn)measurementChanged()方法,使之可以更新當前狀況、氣象統(tǒng)計以及天氣預(yù)報的三個值。WeatherData類中有三個獲取測量值的方法,分別用以獲取溫度、濕度以及氣壓;getTemperature()getHumidity()getPressure()當有新的測量值生效時可以調(diào)用measurementsChanged()方法。(我們不必知道或者關(guān)心這個方法是如何被調(diào)用的,只需要知道有這個方法即可。)

我們需要實現(xiàn)三個天氣數(shù)據(jù)的顯示功能:平均溫度:22°最低溫度:16°最高溫度:28°目前狀況溫度:25°濕度:60氣壓:天氣預(yù)報系統(tǒng)必須具備擴展性----其他開發(fā)人員可以創(chuàng)建新的自定義的顯示,用戶根據(jù)需要可以增加或者刪除顯示功能。

?第一次實現(xiàn)……:在Weather-O-Rama的開發(fā)人員的指導(dǎo)下在measurementsChanged()方法中加入了我們自己的代碼。

通過調(diào)用getTemperature(),getHumidity(),getPressure()(這三個方法已經(jīng)被實現(xiàn)了)獲取最近的天氣數(shù)據(jù)。更新這些顯示的功能:調(diào)用每一個顯示的功能來更新其顯示項(最新的天氣數(shù)據(jù))我們的實現(xiàn)有什么問題嗎?A.面向?qū)崿F(xiàn)在編程,而不是面向接口;B.任意一個新的顯示功能要求,我們必須修改代碼;C.我們無法在運行時增加(或者刪除)顯示的功能;D.顯示功能沒有通用的接口;E.對于容易變化的部分我們沒有實現(xiàn)封裝;F.對于WeatherData類來說,我們違背了類的開-閉原則(我們在WeatherData類里加入了新的代碼,使得WeatherData類發(fā)生了改變)。

在此處我們是用代碼具體實現(xiàn)了Display功能,將來我們?nèi)绻朐黾踊蛘邉h除Display功能將變得很困難,除非我們又來修改這些代碼。從分析來看,這些地方是屬于容易變化的部分,我們應(yīng)該把這些部分封裝起來,使得由于這些變動而不會改變原有的代碼。這里的實現(xiàn)看起來我們似乎已經(jīng)使用了一個通用的接口來告訴Display功能?它們都有一個update()方法來獲取temp,humidity,和Pressure的值。很顯然,系統(tǒng)的維護性很不好。

觀察者模式的構(gòu)成:Publishers(發(fā)行者)+Subscribers(訂閱者)

=ObserverPattern(觀察者模式)

一對多當主題內(nèi)的數(shù)據(jù)改變,就會通知觀察者依賴的對象(Observer依賴于Subject,當Subject的數(shù)據(jù)或者狀態(tài)發(fā)聲改變時,Observer可以自動得到通知和更新。)Observer模式描述了如何建立這種關(guān)系。這一描述中的關(guān)鍵對象是目標(subject)和觀察者(observer)。一個目標可以有任意數(shù)目的依賴它的觀察者。一旦目標的狀態(tài)發(fā)生改變,所有的觀察者都得到通知。作為對這個通知的響應(yīng),每個觀察者都將查詢目標以使其狀態(tài)與目標的狀態(tài)同步。這種交互也稱為發(fā)布-訂閱。目標是通知的發(fā)布者。它發(fā)出通知時并不需要知道誰是它的觀察者??梢杂腥我鈹?shù)目的觀察者訂閱并接收通知。4.適用性在以下任一情況下可以使用觀察者描述:當一個抽象模型有兩個方面,其中一個方面依賴于另一方面。將這二者封裝在獨立的對象中以使它們可以各自獨立的改變和復(fù)用。當對一個對象的改變需要同時改變其他對象,而不知道具體有多少對象有待改變。當一個對象必須通知其他對象,而它又不能假定其他對象是誰。換言之,你不希望這些對象是緊密耦合的。5.結(jié)構(gòu)6.參與者Subject(目標):目標知道它的觀察者??梢杂腥我舛嗟挠^察者觀察同一個目標;提供注冊和刪除觀察者對象的接口。Observer(觀察者):為那些在目標發(fā)生改變時需獲得通知的對象定義一個更新接口。ConcreteSubject(具體目標):將有關(guān)狀態(tài)存入各自ConcreteObserver對象;當它的狀態(tài)發(fā)生改變時,向它的各個觀察者發(fā)出通知。ConcreteObserver(具體觀察者):維護一個指向ConcreteSubject對象的引用;存儲有關(guān)狀態(tài),這些狀態(tài)應(yīng)與目標的狀態(tài)保持一致;實現(xiàn)Observer的更新接口以使自身狀態(tài)與目標的狀態(tài)保持一致。模式代碼原型staticvoidMain()

{

//ConfigureObserverpattern

ConcreteSubjects=newConcreteSubject();

s.Attach(newConcreteObserver(s,"X"));

s.Attach(newConcreteObserver(s,"Y"));

s.Attach(newConcreteObserver(s,"Z"));

//Changesubjectandnotifyobservers

s.SubjectState="ABC";

s.Notify();

//Waitforuser

Console.ReadKey();

}OutputObserverX'snewstateisABC

ObserverY'snewstateisABC

ObserverZ'snewstateisABCabstractclassSubject

{

privateList<Observer>_observers=newList<Observer>();

publicvoidAttach(Observerobserver)

{

_observers.Add(observer);

}

publicvoidDetach(Observerobserver)

{

_observers.Remove(observer);

}

publicvoidNotify()

{

foreach(Observeroin_observers)

{

o.Update();

}

}

}classConcreteSubject:Subject

{

privatestring_subjectState;

//Getsorsetssubjectstate

publicstringSubjectState

{

get{return_subjectState;}

set{_subjectState=value;}

}

}abstractclassObserver

{

publicabstractvoidUpdate();

}classConcreteObserver:Observer

{

privatestring_name;

privatestring_observerState;

privateConcreteSubject_subject;

//Constructor

publicConcreteObserver(

ConcreteSubjectsubject,stringname)

{

this._subject=subject;

this._name=name;

}

publicoverridevoidUpdate()

{

_observerState=_subject.SubjectState;

Console.WriteLine("Observer{0}'snewstateis{1}",

_name,observerState);

}

//Getsorsetssubject

publicConcreteSubjectSubject

{

get{return_subject;}

set{_subject=value;}

}

}7.協(xié)作當ConcreteSubject發(fā)生任何可能導(dǎo)致其觀察者與其自身狀態(tài)不一致的改變時,它將通知它的各個觀察者。在得到一個具體目標的改變通知后,ConcreteObserver對象可向目標對象查詢信息。ConcreteObserver使用這些信息以使它的狀態(tài)與目標對象的狀態(tài)一致。8.效果Observer描述允許你獨立的改變目標和觀察者。你可以單獨復(fù)用目標對象而無需同時復(fù)用其觀察者,反之亦然。它也使你可以在不該點目標和其他的觀察者的前提下增加觀察者。下面是觀察者描述其他一些優(yōu)缺點:1.目標和觀察者間的抽象耦合。2.支持廣播通信3.意外的更新9.實現(xiàn)1.創(chuàng)建目標到其觀察者之間的映射。2.觀察多個目標。3.誰觸發(fā)更新4.對已刪除目標的懸掛引用5.在發(fā)出通知前確保目標的狀態(tài)自身是一致的6.避免特定于觀察者的更新協(xié)議-推/拉模型7.顯式的指定感興趣的改變8.封裝復(fù)雜的更新語義9.結(jié)合目標類和觀察者類10.代碼示例見文檔。11.使用Java內(nèi)置的觀察者模式:

java.util包內(nèi)包含最基本的Observer接口與Observable類;這和我們的Subject接口與Observer接口很相似。Observer接口與Observable類使用上更方便,因為許多功能都已經(jīng)事先準備好了。有了Java內(nèi)置的支持,你只需要擴展(繼承)Observable,并告訴它何時該通知觀察者,一切就完成了,剩下的事API會幫你做。

Java內(nèi)置的觀察者模式如何運作:將對象變成觀察者:實現(xiàn)觀察者接口(java.util.Observer),然后調(diào)用任何Observable對象的addObserver()方法。不想再當觀察者時,調(diào)用deleteObserver().可觀察者送出通知:利用擴展java.util.Observable接口產(chǎn)生“可觀察者類”先調(diào)用setChanged()方法,標記狀態(tài)已經(jīng)改變的事實;調(diào)用兩種notifyObservers()方法中的一個notifyObservers()notifyObervers(Objectarg)觀察者接收通知:update(Observableo,Objectarg)主題本身當作第一個變量,好讓觀察者知道是哪個主題通知它的;數(shù)據(jù)對象作為第二個變量setChanged(){changed=true}notifyObservers(Objectarg){if(changed){foreveryobserveronthelist{callupdate(this,arg)}changed=false

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論