肖永剛
(文山學院計科系,云南文山663000)
校園中存在著許多的對象,例如校園、教師、學生等,這些對象代表著真實校園中的各種實體。在真實的校園中消息是這樣傳遞的,首先校園有了一個消息,它需要將這個消息通知教師,再由教師將這個消息通知學生。或者,教師有了一個消息,他需要將這個消息通知學生,但不必將這個消息通知校園。消息總是從較高的層次向較低的層次傳遞,不會反向的從較低的層次向較高的層次傳遞。這是一種自頂向下式的消息傳遞機制。
同樣的,在設計虛擬校園[1]時,也要實現這樣的一種消息傳遞方式。校園、教師和學生等對象構成了整個虛擬校園的基本元素。文章只介紹了這三者之間的消息傳遞機制,以簡化需要討論的問題。
觀察者模式[2]在對象之間定義了一種一對多的依賴關系。當一個對象(發布者)的狀態發生變化時,其它的對象(觀察者),會馬上感知或接受到這種變化,所以觀察者模式在開發虛擬校園時非常有用。對比兩種設計虛擬校園的方法,一種沒有使用觀察者模式,而只是基于組合原則來構建系統,另一種應用了觀察者模式來設計開發虛擬校園,在校園、教師和學生三個對象之間建立起一對多的依賴關系。文章用對比的方式來說明應用觀察者模式設計帶來的好處[3]。
類圖如圖1所示,校園、教師和學生通過組合的方式聯系在一起,組合原則廣泛地應用于這個設計中。Campus類包含一個實體變量teachers,用來代表教師對象,即消息要傳遞給誰。Teacher類包含一個實體變量students,代表學生對象,即要繼續將消息傳遞給誰。三個類之間通過變量teachers和變量students進行訪問。

圖1 應用組合方式構建的系統
序列圖[4]如圖2所示,系統生成參與消息傳遞的對象,分別屬于 Campus、Teacher和 Student類。在對象內部已經指定了消息的發送者和接受者,在系統運行的過程中不會也不能更改它們。首先Campus類產生一個消息并將它傳遞給Teacher類,通過調用Campus類的broadcast方法實現。然后Teacher類接受這個消息并將它傳遞給Student類,通過調用Teacher類的 receiveMessage和 broadcast方法實現。最后Student類接受這個消息,通過調用Student類的receiveMessage方法實現。這樣的方式可以實現消息的自頂向下的傳遞,滿足系統設計的要求。

圖2 應用組合方式時的序列圖
但是這種設計方式有它的不足之處。一方面,當要擴展虛擬校園的功能時,比方說增加一些對象,這些對象同樣要參與到消息傳遞的過程當中,此時就需要對已有類的定義代碼進行修改,定義更多的實體變量來代表新加入的對象。當加入到系統中的對象越來越多時,這種修改的工作量將變得很大。產生錯誤的幾率也隨之增加,系統的可維護性變得很差。另一方面,這個設計中沒有提供一種靈活的更改消息發送或接受對象的方法。在系統運行時,不能動態的將對象加入到消息傳遞過程中,或從消息傳遞過程中將對象移除,因為這些都是在類的定義中預先指定了的。通過這種方式設計的系統缺少靈活性。
應用觀察者模式重新設計了虛擬校園,系統在可擴展性和靈活性上都獲得很大的提高,類圖如圖3所示,Campus類是發布者;Teacher類有兩個身份,既可以是發布者又可以是觀察者,Student類只能作為觀察者。當Campus類或者Teacher類發送消息時,它們相應的觀察者將會收到消息。采用這樣的設計方式,整個系統的靈活性得到了提高。只要一個對象實現了發布者接口,它就可以是發布者,不管這個對象實際上是做什么的[5]。同樣,只要一個對象實現了觀察者接口,它就可以是觀察者。所以,當要擴展系統功能時,可以很方便地添加一些實現了這兩種接口的類,而不需要對已有的類進行修改。唯一需要保證的是,這些類實現了相應的接口。

圖3 應用觀察者模式構建的系統
虛擬校園系統在校園、教師和學生之間建立了兩個一對多的依賴關系。一個是Campus類與Teacher類,Teacher類依賴Campus類傳遞消息;另一個是Teacher類與 Student類,Student類依賴 Teacher類傳遞消息。Teacher類扮演了兩種身份,既是消息的接受方又是消息的發送方。
在Subject接口中,方法attach用來注冊觀察者,detach用來注銷觀察者,方法notify用來通知觀察者;在Observer接口中,方法receiveMessage用來接受消息。在Campus類中,變量observers用來代表消息的觀察者列表,方法getMessage用來產生新的消息;在Teacher類中,變量observers用來代表消息的觀察者列表,變量campus用來代表消息的發布者,方法getMessage用來產生新的消息;在Student類中,變量campus用來代表消息的發布者,方法get-Message用來產生新的消息。
序列圖如圖4所示,當Campus類傳遞消息之前,它需要調用attach和detach方法決定消息由誰接受。一旦產生一條消息,它首先將這條消息傳遞給Teacher類,Teacher類收到消息后,也需要調用attach和detach方法決定消息由誰接受,再將這條消息傳遞給Student類。這樣,通過動態的注冊和注銷觀察者,以及利用不同對象之間方法的依次調用,實現了消息自頂向下的傳遞。

圖4 應用觀察者模式時的序列圖
總體來看,應用設計者模式的優點大于缺點。首先,系統獲得良好的可擴展性,可以很容易的向系統中添加新的對象,需要做的只是要那些新加入的對象實現Subject接口或Observer接口,然后,可以在需要它們進行消息傳遞的時候注冊到觀察者列表,在不需要進行消息傳遞的時候注銷出觀察者列表。其次,對于本系統中參與消息傳遞的對象,因為發布者和觀察者之間并不存在很緊密的聯系,它們可以獨立地應用在其它的系統中。對其中某個對象的復用不受到另外對象的影響或限制。最后,如果對某個對象進行了修改,不會影響其它的對象,不需要修改已有的對象。所以,采用了觀察者模式重新設計以后,系統獲得了良好的可擴展性和靈活性,有利于系統的修改和維護。
可以看到,重新設計以后將會帶來更多的接口和方法。每個發布者或接受者都需要某個接口去定義。但是對于一個項目來說,這可能會帶來管理上的困難,因為跟蹤或維護這些類的工作量會增多。
[1] 劉巧紅.計算機虛擬校園的建造與人機交互的實現[J].計算機工程與設計,2006,(19):4332 -4335.
[2] Eric Freeman,Elisabeth Freeman,Kathy Sierra & Bert Bates.Head First Design Patterns[M].USA:O’reilly Media,2004:51.
[3] 廖志堅,蔣明亮.設計模式在廣東高新區產業地圖研究系統中的應用[J].科技管理研究,2011,(2):123-126.
[4] Dan Pilone& Russ Miles.Head First Software Development[M].USA:O’reilly Media,2007:436-437.
[5] Kathy Sierra& Bert Bates.Head First Java[M].USA:O’reilly Media,2007:226.