使用Publish/Subscribe 設(shè)計(jì)模式達(dá)到對(duì)象間數(shù)據(jù)同步
2024-07-21 02:25:38
供稿:網(wǎng)友
使用publish/subscribe 設(shè)計(jì)模式達(dá)到對(duì)象間數(shù)據(jù)同步
應(yīng)用程序經(jīng)常需要更改和交換數(shù)據(jù),必須傳送這些更改后數(shù)據(jù)以達(dá)到對(duì)象的同步,尤其在多窗口用戶界面應(yīng)用程序中更要求這種數(shù)據(jù)的同步協(xié)調(diào),在這一類應(yīng)用程序中,潛在的數(shù)據(jù)更新信息一定要反映到所有被包含的子窗體中。
例如一個(gè)人員信息管理的應(yīng)用程序。一次可以打開(kāi)多個(gè)包含一個(gè)人名字的窗口,如果你在其中一個(gè)窗口中修改并報(bào)存了這個(gè)人的名字,你將期望對(duì)名字改變應(yīng)立即顯示在其它全部窗體內(nèi)。可以通過(guò)使用publish/subscribe設(shè)計(jì)模式來(lái)完成這種功能。這種設(shè)計(jì)模式是observer 模式(見(jiàn)圖一)的一種變體。observer 模式在design patterns, elements of reusable object oriented software書(shū)中有很詳細(xì)的描述,在observer 模式中,一個(gè)對(duì)象(observer觀察者)被注冊(cè)到另一對(duì)象(主體subject),用于監(jiān)聽(tīng)事件。觀察者(observer)暗中地反映(主體subject)的變化。
圖一
publish/subscribe模式(參見(jiàn)圖二),在主體(subject)和觀察者(observer)之間增加了一層間隔。 這個(gè)層移除了在觀察者(observer)和主體(subject)之間的捆綁并且在這兩之間建立一種松耦合的關(guān)系。 event channel 可以被描述成一個(gè)數(shù)據(jù)中心。
圖二
publisher (就是在觀察者(observer)模式中的主體(subject)) 向這個(gè)event channel.發(fā)布事件。event channel 的責(zé)任就是向所有的subscribers (就是在觀察者(observer)模式中的觀察者(observer))散布事件。一個(gè)應(yīng)用程序可以包含一個(gè)或多個(gè)event channel,所以,要向每個(gè)感興趣的subscribers來(lái)散布不同的事件。此外,在觀察者(observer)模式中事件僅僅來(lái)自特殊的來(lái)源,在publish/subscribe模式中任何注意event channel的對(duì)象都可以發(fā)布事件。
這個(gè)構(gòu)造移除了觀察者(observer) and主體(subject)之間的依賴。結(jié)果是你可以為你的應(yīng)用程序增加更多的通用設(shè)計(jì),此外,通過(guò)要求在publisher和subscriber之間的沒(méi)有直接的關(guān)系,它大大增加你的應(yīng)用程序的可維護(hù)性。
使用publish/subscribe模式
通過(guò)一個(gè)簡(jiǎn)單的例子來(lái)學(xué)習(xí)publish/subscribe模式是如何實(shí)現(xiàn)的。eventapp. eventapp是一個(gè)擁有一個(gè)mdi窗體和很多子窗體的應(yīng)用環(huán)境。(下載本文代碼).
在你的程序中,你將需要?jiǎng)?chuàng)造一系列的基類來(lái)實(shí)現(xiàn)publish/subscribe模式。 在工程里的其他類都從這些基類派生而來(lái)(見(jiàn)圖三)。 eventapp 應(yīng)用程序有如下3 個(gè)基類:
圖三
clseventchannel ----------------------為構(gòu)建event channels的一個(gè)抽象類。
clsevent --------------------------為構(gòu)建事件的類型使用的一個(gè)抽象類。 它暴露了4個(gè)屬性:
name: 事件的名字
value: 事件的價(jià)值
extradata: 被關(guān)聯(lián)那些事件的其它數(shù)據(jù)
origin: 可選擇的參考鑒定事件的 publisher
frmsubscriber – 用于創(chuàng)建窗口、接收事件的一個(gè)抽象windows form
為了使一應(yīng)用工作,你需要建立從那些基類繼承的幾個(gè)具體的類。 在這個(gè)例子當(dāng)中,這些類是:
clsdataevents - 從clseventchannel類繼承的一個(gè)具體的類。 在應(yīng)用程序中,將它作為event channel來(lái)使用,它被用來(lái)向那些潛在的數(shù)據(jù)模型散布更新的信息。
clsdataevent - 從clsevent類繼承并且用來(lái)創(chuàng)建事件,呈現(xiàn)潛在數(shù)據(jù)的更新的一個(gè)具體的類。 ( 要?jiǎng)?chuàng)建一個(gè)繼承窗體,你可以在解決方案資源管理器中選擇" 添加(add)-> 添加繼承的窗體(inherited windows form)" 的快捷菜單 。
frmlist – 派生自frmsubscriber類的一個(gè)具體的類。它是mdi窗體的一個(gè)子窗體,用于顯示數(shù)據(jù)列表。在這個(gè)例子中,這個(gè)窗體通過(guò)硬編碼用一個(gè)listview控件顯示了10條數(shù)據(jù)。
eventapp 如何工作
當(dāng)eventapp 被啟動(dòng)時(shí), frmmain( mdi 父窗體) 創(chuàng)造一個(gè)數(shù)據(jù)event channel實(shí)例-----clsdataevents:
private sub frmmain_load(byval sender as object, _
byval e as system.eventargs) handles mybase.load
mobjdataeventchannel = new clsdataevents()
me.ismdicontainer = true
me.text = "publish/subscribe event sample"
me.windowstate = formwindowstate.maximized
end sub
當(dāng)mdi窗體被運(yùn)行時(shí),你可以在菜單中選擇"file->new list"來(lái)創(chuàng)建一個(gè)frmlist類的實(shí)例。
private sub menuitem2_click(byval sender as _
system.object, byval e as system.eventargs) _
handles menuitem2.click
dim objnewform as frmlist
objnewform = new frmlist()
mobjdataeventchannel.attachsubscriber(objnewform)
objnewform.mdiparent = me
objnewform.show()
end sub
當(dāng)創(chuàng)建了子窗體以后,它將被注冊(cè)到event channel,在注冊(cè)過(guò)程期間,event channel將要初始化subscriber。
public overridable sub initialize(byval token as _
string, byval eventchannel as clseventchannel)
mstrtoken = token
mobjeventchannel = eventchannel
end sub
注冊(cè)會(huì)員,創(chuàng)建你的web開(kāi)發(fā)資料庫(kù),