實現範例的Observer設計模式 事件 委託

2021-04-20 02:59:04 字數 3676 閱讀 3544

上面的例子已不足以再進行下面的講解了,我們來看乙個新的範例,因為之前已經介紹了很多的內容,所以本節的進度會稍微快一些:

假設我們有個高檔的熱水器,我們給它通上電,當水溫超過95度的時候:1、揚聲器會開始發出語音,告訴你水的溫度;2、液晶屏也會改變水溫的顯示,來提示水已經快燒開了。

現在我們需要寫個程式來模擬這個燒水的過程,我們將定義乙個類來代表熱水器,我們管它叫:heater,它有代表水溫的字段,叫做temperature;當然,還有必不可少的給水加熱方法boilwater(),乙個發出語音警報的方法makealert(),乙個顯示水溫的方法,showmsg()。

namespace delegate }}

// 發出語音警報

private

void makealert(int param) 度了:" , param);

}// 顯示水溫

private

void showmsg(int param) 度。" , param);}}

class

program }}

上面的例子顯然能完成我們之前描述的工作,但是卻並不夠好。現在假設熱水器由三部分組成:熱水器、警報器、顯示器,它們來自於不同廠商並進行了組裝。那麼,應該是熱水器僅僅負責燒水,它不能發出警報也不能顯示水溫;在水燒開時由警報器發出警報、顯示器顯示提示和水溫。

這時候,上面的例子就應該變成這個樣子:   

// 熱水器

public

class

heater }}

// 警報器

public

class

alarm 度了:" , param);}}

// 顯示器

public

class

display度。" , param);}}

這裡就出現了乙個問題:如何在水燒開的時候通知報警器和顯示器?在繼續進行之前,我們先了解一下observer設計模式,observer設計模式中主要包括如下兩類物件:

subject:監視物件,它往往包含著其他物件所感興趣的內容。在本範例中,熱水器就是乙個監視物件,它包含的其他物件所感興趣的內容,就是temprature欄位,當這個欄位的值快到100時,會不斷把資料發給監視它的物件。

observer:監視者,它監視subject,當subject中的某件事發生的時候,會告知observer,而observer則會採取相應的行動。在本範例中,observer有警報器和顯示器,它們採取的行動分別是發出警報和顯示水溫。

在本例中,事情發生的順序應該是這樣的:

警報器和顯示器告訴熱水器,它對它的溫度比較感興趣(註冊)。

熱水器知道後保留對警報器和顯示器的引用。

熱水器進行燒水這一動作,當水溫超過95度時,通過對警報器和顯示器的引用,自動呼叫警報器的makealert()方法、顯示器的showmsg()方法。

類似這樣的例子是很多的,gof對它進行了抽象,稱為observer設計模式:observer設計模式是為了定義物件間的一種一對多的依賴關係,以便於當乙個物件的狀態改變時,其他依賴於它的物件會被自動告知並更新。observer模式是一種松耦合的設計模式。

我們之前已經對委託和事件介紹很多了,現在寫**應該很容易了,現在在這裡直接給出**,並在注釋中加以說明。

using system;

using system.collections.generic;

using system.text;

namespace delegate }}

}}// 警報器

public

class

alarm 度了:", param);}}

// 顯示器

public

class

display 度。", param);}}

class

program }}

輸出為:

alarm:嘀嘀嘀,水已經 96 度了:

alarm:嘀嘀嘀,水已經 96 度了:

display:水快燒開了,當前溫度:96度。

// 省略...

儘管上面的範例很好地完成了我們想要完成的工作,但是我們不僅疑惑:為什麼.net framework 中的事件模型和上面的不同?為什麼有很多的eventargs引數?

在回答上面的問題之前,我們先搞懂 .net framework的編碼規範:

再做一下說明:

委託宣告原型中的object型別的引數代表了subject,也就是監視物件,在本例中是 heater(熱水器)。**函式(比如alarm的makealert)可以通過它訪問觸發事件的物件(heater)。

eventargs 物件包含了observer所感興趣的資料,在本例中是temperature。

上面這些其實不僅僅是為了編碼規範而已,這樣也使得程式有更大的靈活性。比如說,如果我們不光想獲得熱水器的溫度,還想在observer端(警報器或者顯示器)方法中獲得它的生產日期、型號、**,那麼委託和方法的宣告都會變得很麻煩,而如果我們將熱水器的引用傳給警報器的方法,就可以在方法中直接訪問熱水器了。

現在我們改寫之前的範例,讓它符合 .net framework 的規範:

using system;

using system.collections.generic;

using system.text;

namespace delegate

}// 可以供繼承自 heater 的類重寫,以便繼承類拒絕其他物件對它的監視

protected

virtual

void onboiled(boiledeventargs e)

}// 燒水。

public

void boilwater() }}

}// 警報器

public

class

alarm - : ", heater.area, heater.type);

console.writeline("alarm: 嘀嘀嘀,水已經 度了:", e.temperature);

console.writeline();}}

// 顯示器

public

class

display - : ", heater.area, heater.type);

console.writeline("display:水快燒開了,當前溫度:度。", e.temperature);

console.writeline();}}

class

program }}

輸出為:

alarm:china xian - realfire 001:

alarm: 嘀嘀嘀,水已經 96 度了:

alarm:china xian - realfire 001:

alarm: 嘀嘀嘀,水已經 96 度了:

alarm:china xian - realfire 001:

alarm: 嘀嘀嘀,水已經 96 度了:

display:china xian - realfire 001:

display:水快燒開了,當前溫度:96度。

// 省略 ...

在第二個稍微複雜點的熱水器的範例中,我向大家簡要介紹了 observer設計模式,並通過實現這個範例完成了該模式,隨後講述了.net framework中委託、事件的實現方式。

希望這篇文章能給你帶來幫助。

設計模式 Observer實現

observer模式的典型實現 subject.h note 1.subject類依賴obserer介面類。2.attach又叫register subscribe addobserver,detach又叫release unsubscribe removeobserver。todo attach方...

設計模式Observer

observer設計模式的定義 定義了物件之間的一對多的依賴,這樣以來,當乙個物件改變狀態時,它的所有依賴者都會受到通知並自動更新。ifndef subjec h define subjec h include observer.h class subject subject subject sub...

Observer設計模式

observer設計模式是針對 乙個物件對多個物件中,乙個物件發生狀態改變,其他附屬物件發生相應的更新。是一種松耦合的設計模式。例子 假設我們有個高檔的熱水器,我們給它通上電,當水溫超過95度的時候 1 揚聲器會開始發出語音,告訴你水的溫度 2 液晶屏也會改變水溫的顯示,來提示水已經快燒開了。現在我...