深入理解Java中觀察者模式與委托的對比_第1頁
深入理解Java中觀察者模式與委托的對比_第2頁
深入理解Java中觀察者模式與委托的對比_第3頁
深入理解Java中觀察者模式與委托的對比_第4頁
深入理解Java中觀察者模式與委托的對比_第5頁
已閱讀5頁,還剩8頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第深入理解Java中觀察者模式與委托的對比目錄代碼背景觀察者模式介紹實現(xiàn)觀察者(學(xué)生)通知者(老師)Main方法觀察者通知者事件事件處理委托介紹總結(jié)

代碼背景

一個班級,有兩類學(xué)生,A類:不學(xué)習(xí),玩,但是玩的東西不一樣,有的是做游戲,有的是看電視

B類:放哨的學(xué)生,專門看老師的動向,如果老師進(jìn)班了就立即通知大家。

如此就形成了一個需求,放哨的學(xué)生要通知所有玩的學(xué)生:老師來了,而不同的學(xué)生有不同的反應(yīng),有的馬上把電視關(guān)閉,有的停止玩游戲。

觀察者模式

介紹

觀察者模式:定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象。

這個主題對象在狀態(tài)發(fā)生變化時,會通知所有的觀察者對象,使他們能夠自動更新自己。

主要解決:一個對象狀態(tài)改變給其他對象通知的問題,而且要考慮到易用和低耦合,保證高度的協(xié)作。

何時使用:一個對象(目標(biāo)對象)的狀態(tài)發(fā)生改變,所有的依賴對象(觀察者對象)都將得到通知,進(jìn)行廣播通知。

如何解決:使用面向?qū)ο蠹夹g(shù),可以將這種依賴關(guān)系弱化。

關(guān)鍵代碼:在抽象類里有一個ArrayList存放觀察者們。

實現(xiàn)

觀察者(學(xué)生)

/**

*抽象的觀察者

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:32

publicinterfaceObserver{

publicabstractvoidupdateState();

*具體的觀察者

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:39

publicclassConcreteObserverimplementsObserver{

//觀察者的姓名

privateStringname;

//觀察者的狀態(tài)

privateStringobserverState;

//明確具體的通知者

privateConcreteSubjectsubject;

//getset方法省略

publicConcreteObserver(Stringname,ConcreteSubjectsubject){

=name;

this.subject=subject;

@Override

publicvoidupdateState(){

observerState=subject.getSubjectState();

System.out.println(name+"在打游戲");

Stringstr=String.format("觀察者%s的:新狀態(tài)是%s",name,observerState);

System.out.println(str);

*具體的觀察者

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:39

publicclassConcreteObserver2implementsObserver{

//觀察者的姓名

privateStringname;

//觀察者的狀態(tài)

privateStringobserverState;

//明確具體的通知者

privateConcreteSubjectsubject;

//getset方法省略

publicConcreteObserver2(Stringname,ConcreteSubjectsubject){

=name;

this.subject=subject;

@Override

publicvoidupdateState(){

observerState=subject.getSubjectState();

System.out.println(name+"在看電視");

Stringstr=String.format("觀察者%s:新狀態(tài)是%s",name,observerState);

System.out.println(str);

}

通知者(老師)

/**

*抽象的通知者

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:30

publicabstractclassSubject{

//管理觀察者的集合

privateListObserverobservers=newArrayList();

//增加觀察者

publicvoidadd(Observerobserver){

observers.add(observer);

//減少觀察者

publicvoiddetach(Observerobserver){

observers.remove(observer);

*通知所有的觀察者

publicvoidnotifyMsg(){

for(Observerobserver:observers){

observer.updateState();

*具體的通知者

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:38

publicclassConcreteSubjectextendsSubject{

//通知者的狀態(tài)

privateStringsubjectState;

//getset方法

publicStringgetSubjectState(){

returnsubjectState;

publicvoidsetSubjectState(StringsubjectState){

this.subjectState=subjectState;

}

Main方法

/**

*控制臺Main方法

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/10-15:48

publicclassMainTest{

publicstaticvoidmain(String[]args){

//創(chuàng)建一個主題/通知者

ConcreteSubjectsubject=newConcreteSubject();

//new出觀察者(學(xué)生)

ConcreteObserverstudentZhang=newConcreteObserver("小張",subject);

ConcreteObserverstudentLiu=newConcreteObserver("小劉",subject);

ConcreteObserverstudentWang=newConcreteObserver("小王",subject);

//將觀察者添加到通知隊列里

subject.add(studentZhang);

subject.add(studentLiu);

subject.add(studentWang);

//通知者(老師)狀態(tài)修改,通知每個學(xué)生

subject.setSubjectState("老師回來了,我要好好學(xué)習(xí)");

subject.notifyMsg();

System.out.println("-----------");

}

委托介紹

委托可以看做是函數(shù)的抽象,是函數(shù)的類。委托的實例將代表一個具體的函數(shù)

一個委托可以搭載多個方法,所有的方法被依次喚起??梢允刮袑ο笏钶d的方法并不需要屬于同一類。

委托事件模型可以由三個組件定義:事件、事件源和事件偵聽器。

委托的實現(xiàn)簡單來講就是用反射來實現(xiàn)的。

實現(xiàn)

觀察者

/**

*監(jiān)聽器/觀察者玩游戲

*事件監(jiān)聽器

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:17

publicclassPlayingGameListener{

publicPlayingGameListener(){

System.out.println("我正在玩游戲開始時間"+newDate());

publicvoidstopPlayingGame(Datedate){

System.out.println("老師來了,快回到座位上,結(jié)束時間"+date);

*監(jiān)聽器/觀察者看電視

*事件監(jiān)聽器

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:17

publicclassWatchingTVListener{

publicWatchingTVListener(){

System.out.println("我正在看電視"+newDate());

publicvoidstopWatchingTV(Datedate){

System.out.println("老師來了,快關(guān)閉電視。結(jié)束時間"+date);

}

通知者

/**

*通知者的抽象類

*事件源

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:15

publicabstractclassNotifier{

//每個通知者都有一個需要通知的隊列(通知:對象、方法、參數(shù))

privateEventHandlereventHandler=newEventHandler();

publicEventHandlergetEventHandler(){

returneventHandler;

publicvoidsetEventHandler(EventHandlereventHandler){

this.eventHandler=eventHandler;

//增加需要幫忙放哨的學(xué)生

publicabstractvoidaddListener(Objectobject,StringmethodName,Object...args);

//告訴所有要幫忙放哨的學(xué)生:老師來了

publicabstractvoidnotifyX();

*通知者的子類,放哨人

*事件源

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:15

publicclassGoodNotifierextendsNotifier{

@Override

publicvoidaddListener(Objectobject,StringmethodName,Object...args){

System.out.println("有新的同學(xué)委托盡職盡責(zé)的放哨人!");

this.getEventHandler().addEvent(object,methodName,args);

@Override

publicvoidnotifyX(){

System.out.println("盡職盡責(zé)的放哨人告訴所有需要幫忙的同學(xué):老師來了");

try{

//優(yōu)化:異步通知

this.getEventHandler().notifyX();

}catch(Exceptione){

e.printStackTrace();

}

事件

/**

*抽象出的事件類,也可以稱為方法類

*事件

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:03

publicclassEvent{

//要執(zhí)行方法的對象

privateObjectobject;

//要執(zhí)行的方法名稱

privateStringmethodName;

//要執(zhí)行方法的參數(shù)

privateObject[]params;

//要執(zhí)行方法的參數(shù)類型

privateClass[]paramTypes;

//若干settergetter

publicObjectgetObject(){

returnobject;

publicStringgetMethodName(){

returnmethodName;

publicvoidsetMethodName(StringmethodName){

this.methodName=methodName;

publicObject[]getParams(){

returnparams;

publicvoidsetParams(Object[]params){

this.params=params;

publicClass[]getParamTypes(){

returnparamTypes;

publicvoidsetParamTypes(Class[]paramTypes){

this.paramTypes=paramTypes;

publicEvent(){

publicEvent(Objectobject,StringmethodName,Object...args){

this.object=object;

this.methodName=methodName;

this.params=args;

contractParamTypes(this.params);

//根據(jù)參數(shù)數(shù)組生成參數(shù)類型數(shù)組

privatevoidcontractParamTypes(Object[]params){

this.paramTypes=newClass[params.length];

for(inti=0;iparams.length;i++){

this.paramTypes[i]=params[i].getClass();

//執(zhí)行該對象的該方法

publicvoidinvoke()throwsException{

//通過class,method,paramTypes確定執(zhí)行哪個類的哪個方法

Methodmethod=object.getClass().getMethod(this.getMethodName(),this.getParamTypes());

if(null==method){

return;

//方法執(zhí)行

method.invoke(this.getObject(),this.getParams());

}

事件處理

/**

*管理哪些事件需要執(zhí)行

*管理事件

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:03

publicclassEventHandler{

//是用一個List

privateListEventobjects;

//添加某個對象要執(zhí)行的事件,及需要的參數(shù)

publicvoidaddEvent(Objectobject,StringmethodName,Object...args){

objects.add(newEvent(object,methodName,args));

publicEventHandler(){

objects=newArrayListEvent

//通知所有的對象執(zhí)行指定的事件

publicvoidnotifyX()throwsException{

for(Evente:objects){

e.invoke();

}

Main方法

/**

*啟動類

*@authorPromsing(張有博)

*@version1.0.0

*@since2025/5/8-11:19

publicclassEventMain{

publicstaticvoidmain(String[]args){

//創(chuàng)建一個盡職盡責(zé)的放哨者

NotifiergoodNotifier=newGoodNotifier();

//創(chuàng)建一個玩游戲的同學(xué),開始玩游戲

PlayingGameListenerplayingGameListener=newPlayingGameListener();

//創(chuàng)建一個看電視的同學(xué),開始看電視

WatchingTVListenerwatchingTVListener=newWatchingTVListener();

//玩游戲的同學(xué)告

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論