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

下載本文檔

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

文檔簡(jiǎn)介

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

我們需要?jiǎng)?chuàng)建一個(gè)應(yīng)用程序,可以根據(jù)天氣數(shù)據(jù)對(duì)象來(lái)更新當(dāng)前狀況、氣象統(tǒng)計(jì)以及天氣預(yù)報(bào)的三個(gè)布告板。

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

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

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

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

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

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

=ObserverPattern(觀察者模式)

一對(duì)多當(dāng)主題內(nèi)的數(shù)據(jù)改變,就會(huì)通知觀察者依賴的對(duì)象(Observer依賴于Subject,當(dāng)Subject的數(shù)據(jù)或者狀態(tài)發(fā)聲改變時(shí),Observer可以自動(dòng)得到通知和更新。)Observer模式描述了如何建立這種關(guān)系。這一描述中的關(guān)鍵對(duì)象是目標(biāo)(subject)和觀察者(observer)。一個(gè)目標(biāo)可以有任意數(shù)目的依賴它的觀察者。一旦目標(biāo)的狀態(tài)發(fā)生改變,所有的觀察者都得到通知。作為對(duì)這個(gè)通知的響應(yīng),每個(gè)觀察者都將查詢目標(biāo)以使其狀態(tài)與目標(biāo)的狀態(tài)同步。這種交互也稱為發(fā)布-訂閱。目標(biāo)是通知的發(fā)布者。它發(fā)出通知時(shí)并不需要知道誰(shuí)是它的觀察者??梢杂腥我鈹?shù)目的觀察者訂閱并接收通知。4.適用性在以下任一情況下可以使用觀察者描述:當(dāng)一個(gè)抽象模型有兩個(gè)方面,其中一個(gè)方面依賴于另一方面。將這二者封裝在獨(dú)立的對(duì)象中以使它們可以各自獨(dú)立的改變和復(fù)用。當(dāng)對(duì)一個(gè)對(duì)象的改變需要同時(shí)改變其他對(duì)象,而不知道具體有多少對(duì)象有待改變。當(dāng)一個(gè)對(duì)象必須通知其他對(duì)象,而它又不能假定其他對(duì)象是誰(shuí)。換言之,你不希望這些對(duì)象是緊密耦合的。5.結(jié)構(gòu)6.參與者Subject(目標(biāo)):目標(biāo)知道它的觀察者??梢杂腥我舛嗟挠^察者觀察同一個(gè)目標(biāo);提供注冊(cè)和刪除觀察者對(duì)象的接口。Observer(觀察者):為那些在目標(biāo)發(fā)生改變時(shí)需獲得通知的對(duì)象定義一個(gè)更新接口。ConcreteSubject(具體目標(biāo)):將有關(guān)狀態(tài)存入各自ConcreteObserver對(duì)象;當(dāng)它的狀態(tài)發(fā)生改變時(shí),向它的各個(gè)觀察者發(fā)出通知。ConcreteObserver(具體觀察者):維護(hù)一個(gè)指向ConcreteSubject對(duì)象的引用;存儲(chǔ)有關(guān)狀態(tài),這些狀態(tài)應(yīng)與目標(biāo)的狀態(tài)保持一致;實(shí)現(xiàn)Observer的更新接口以使自身狀態(tài)與目標(biāo)的狀態(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é)作當(dāng)ConcreteSubject發(fā)生任何可能導(dǎo)致其觀察者與其自身狀態(tài)不一致的改變時(shí),它將通知它的各個(gè)觀察者。在得到一個(gè)具體目標(biāo)的改變通知后,ConcreteObserver對(duì)象可向目標(biāo)對(duì)象查詢信息。ConcreteObserver使用這些信息以使它的狀態(tài)與目標(biāo)對(duì)象的狀態(tài)一致。8.效果Observer描述允許你獨(dú)立的改變目標(biāo)和觀察者。你可以單獨(dú)復(fù)用目標(biāo)對(duì)象而無(wú)需同時(shí)復(fù)用其觀察者,反之亦然。它也使你可以在不該點(diǎn)目標(biāo)和其他的觀察者的前提下增加觀察者。下面是觀察者描述其他一些優(yōu)缺點(diǎn):1.目標(biāo)和觀察者間的抽象耦合。2.支持廣播通信3.意外的更新9.實(shí)現(xiàn)1.創(chuàng)建目標(biāo)到其觀察者之間的映射。2.觀察多個(gè)目標(biāo)。3.誰(shuí)觸發(fā)更新4.對(duì)已刪除目標(biāo)的懸掛引用5.在發(fā)出通知前確保目標(biāo)的狀態(tài)自身是一致的6.避免特定于觀察者的更新協(xié)議-推/拉模型7.顯式的指定感興趣的改變8.封裝復(fù)雜的更新語(yǔ)義9.結(jié)合目標(biāo)類和觀察者類10.代碼示例見文檔。11.使用Java內(nèi)置的觀察者模式:

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

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

溫馨提示

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

評(píng)論

0/150

提交評(píng)論