尚 偉,劉志廣,張 沫
(1.中國電子科技集團公司第五十四研究所,河北石家莊050081;2.河北文化信息資源共享中心,河北石家莊050011)
耦合度是標識軟件系統(tǒng)好壞的一個重要屬性,軟件系統(tǒng)中存在過多的耦合會使系統(tǒng)變得復雜,錯誤率增加,從而使系統(tǒng)難于更改和維護。過度的耦合不利于模塊的設計和重用,為了提高模塊化和封裝性,應該盡量減少對象類之間的耦合。在系統(tǒng)設計過程中,特別是系統(tǒng)框架的設計過程中,降低軟件系統(tǒng)的耦合性是改善軟件系統(tǒng)的可維護性、可理解性和可擴展性的關鍵。采用合理的設計模式為目前改善軟件系統(tǒng)耦合性的常用方法。
設計模式是按照建筑設計領域模式思想對軟件設計領域的總結和歸納,對軟件行業(yè)的發(fā)展有重要推動的作用。計算機科學中對設計模式的簡單定義就是對于一類重復出現(xiàn)的問題的一種可重用的解決方案,在軟件工程中一個設計模式對應解決一類軟件設計問題。設計模式是成功的軟件架構設計經(jīng)驗總結,是被實踐證明的可復用的解決方案。設計模式解決了軟件開發(fā)中有關對象的創(chuàng)建、結構和行為等一系列問題。如果多個項目有相同的問題背景,那么可以應用相同的設計模式加以解決。在軟件設計中使用設計模式可以減少各個類之間的依賴和藕合,增強結構復用性,減少因變更所做的設計調整。觀察者設計模式就是這樣的一種低耦合設計技術。
觀察者模式是一種行為性設計模式。它定義了一個對象間一對多的信賴關系,當一個對象改變狀態(tài)時,所有與它有信賴關系的對象都得到通知并自動更新。適用于以下的情況:①一個抽象的模型擁有2個方面,其中一個方面依賴于另一個方面。將這2個方面封裝在獨立的對象中,可以使它們各自獨立地改變和復用;②一個對象改變時,也要改變其他對象,但不知道具體有多少對象需要改變;③一個對象必須通知其他對象自己狀態(tài)的改變,而又不能假定其他對象是誰。使用觀察者模式,可以減少目標和觀察者對象間的耦合程度,并且這種模式支持廣播通信,可以同時改變多個對象的狀態(tài)。
觀察者模式定義了目標對象和觀察者對象之間的一種一對多的依賴關系,當目標對象的狀態(tài)發(fā)生了改變,它要能夠把這一信息通知給所有依賴于它的觀察者對象,而各個觀察者對象根據(jù)通知信息來恰當?shù)貙ψ约旱谋憩F(xiàn)形式進行更新。觀察者模式結構如圖1所示。
圖1 觀察者模式結構
圖1中目標類提供注冊和刪除觀察者對象的接口;而觀察者類為那些在目標發(fā)生改變時需獲得通知的對象定義一個更新接口;當具體目標類的狀態(tài)發(fā)生變化時,負責向它的各個觀察者發(fā)送通知;具體觀察者類存儲有關狀態(tài),實現(xiàn)觀察者的更新接口以使自身狀態(tài)與目標狀態(tài)一致。
如果2個類的訪問或通信是直接通過彼此調用實現(xiàn)的,這樣2個類間的耦合關系就會非常緊密。根據(jù)圖1中的結構可以看出,觀察者模式中目標類與具體觀察者類是通過觀察者這個接口的方式實現(xiàn)彼此間通訊的,而具體觀察者類是負責具體實現(xiàn)該接口以及函數(shù)的類,這種結構實現(xiàn)了接口與實現(xiàn)分離的策略。這樣的設計也使得具體目標與具體觀察者不直接關聯(lián),具體目標變化時通知觀察者,只需通過注冊的觀察者接口完成更新操作(更新的具體實現(xiàn)在具體觀察者類中),即具體目標類不需要知道具體觀察者類,這樣做降低了目標類與具體觀察者類的耦合度。
觀察者模式中目標與觀察者是一對多的關系,在實際的程序設計中目標對象使用一個數(shù)組或鏈表成員變量來維護它的多個觀察者對象。注冊函數(shù)和刪除函數(shù)是添加或刪除觀察者對象的接口。通知函數(shù)是當目標對象狀態(tài)改變時通知它的所有觀察者對象的接口。在目標對象的通知函數(shù)接口中常用數(shù)組或鏈表保存依賴于主題對象的觀察者對象,同時在該接口中將對這些對象進行遍歷,每遍歷到一個觀察者對象時就會調用它的更新函數(shù)接口。更新函數(shù)根據(jù)消息的類型使得觀察者對象對目標對象的狀態(tài)變化做出相應的更新。這樣,目標對象的一個通知函數(shù)執(zhí)行下來,它的所有觀察者對象都更新了。
對具體目標類來說,它從基類(目標類)派生,在基類的基礎上增加了自身的狀態(tài)數(shù)據(jù)。當自身的狀態(tài)數(shù)據(jù)發(fā)生變化時根據(jù)需要向觀察者對象發(fā)送消息。具體的觀察者對象存儲自身狀態(tài),但往往這些狀態(tài)是由觀察者的目標類內容決定的。在邏輯上它們必須保持一致,觀察者在實際的設計中往往設計成一個虛基類,更新函數(shù)是一個純虛函數(shù),這樣才可以利用面向對象的多態(tài)性調用各個觀察者接口的實現(xiàn)類的更新函數(shù)。所以具體的觀察者類的一個重要任務就是實現(xiàn)接口(觀察者的更新函數(shù)),所有具體觀察者類的狀態(tài)維護都靠它來完成。
報警處理系統(tǒng)是管理和接收報警信息,根據(jù)報警事件制定和管理預案,完成報警事件處置的信息系統(tǒng),其主要功能是報警信息處置管理、報警事件檢索分析、管理和收發(fā)格式化信息、文書信息管理、預案管理、勤務通信和短信管理等。
系統(tǒng)的用戶需求可分為不變部分和易變部分。需求的不變部分:①信息的收發(fā)基本功能不變;②收發(fā)文的模板及其相應數(shù)據(jù)的表現(xiàn)形式穩(wěn)定:這些模板都是長期實踐保存下來的,被相應部門廣泛使用的固定格式,一般不會輕易改變;③信息發(fā)送的操作方式相對穩(wěn)定:都是選擇固定的地址,再根據(jù)相應模板進行內容調整后進行發(fā)送。需求的易變部分有:用戶界面易變,報警處理軟件的開發(fā)者畢竟不是軟件的使用者,那么軟件開發(fā)者就必須去適應軟件使用者對軟件界面多變的要求,如何在滿足使用者要求的同時最大程度地減少軟件改寫的開銷成為必須解決的問題。
報警處理系統(tǒng)的主體功能是報警事件的接收顯示及處置。系統(tǒng)對于接收到的報警信息根據(jù)其地理坐標及相應屬性顯示在地圖背景上,并利用聲、光等輔助手段提示用戶。用戶發(fā)現(xiàn)報警后利用系統(tǒng)提供的界面可對報警事件進行處置(關聯(lián)預案、通知相應部門、啟動報警記錄等),處置后的報警信息將在用戶界面進行更新,取消閃爍并停止聲、光提示。
系統(tǒng)中界面顯示和業(yè)務處理功能相分離,外層界面依賴于業(yè)務功能模塊,它們各自又可獨立地改變和復用;此外,兩部分中當一方改變時,也要通知并改變另一方,所以使用MVC(模型—視圖—控制器)架構作為整體結構設計決策。系統(tǒng)中的視圖部分用于顯示模型狀態(tài)、接收數(shù)據(jù)更新請求和發(fā)送用戶請求給控制器。在工程中實例化為地圖顯示相關的類,它們完成報警信息的圖上顯示、啟動閃爍、更新狀態(tài)和停止閃爍燈操作。模型部分用于封裝應用程序狀態(tài)、響應狀態(tài)查詢、處理業(yè)務流程和通知業(yè)務狀態(tài)更新。在工程中實例化為報警信息管理的相關數(shù)據(jù)類,它完成報警數(shù)據(jù)的庫檢索和報警數(shù)據(jù)的結構化等工作。控制器部分用于接收用戶請求、調用模型響應用戶請求和選擇視圖顯示響應結果。工程中實例化為報警信息管理的諸多界面類,完成圖上顯示的控制以及報警信息的管理等操作。主體功能架構圖如圖2所示。
圖2 主體功能架構
每個系統(tǒng)都有自己的特點,不能照抄照搬別人的設計模式,應該找到符合自己的系統(tǒng)設計,走出一條適合自己的開發(fā)之路。為了實現(xiàn)上述系統(tǒng),并盡可能切斷系統(tǒng)各模塊之間的耦合,提高系統(tǒng)的擴展性,引入了觀察者模式。系統(tǒng)的開發(fā)利用VC6.0工具,根據(jù)實際的情況設計中沒有對觀察者模式中目標類做繼承關系的設計(應用中的Subject比較簡單,沒有復雜的層次關系,不需要專門抽象一層來)。下面對系統(tǒng)中的主要類的關系和結構進行說明。
系統(tǒng)中的類可以分為界面類、數(shù)據(jù)類和觀察者類3種。對于每個功能模塊來說,由于使用觀察者接口,界面類的變化(比如使用控件的變化)不需要更改數(shù)據(jù)類,而數(shù)據(jù)類的變化(比如增加了一些新操作)也不需要更改相應的界面類。對象設計結構如圖3所示。
圖3 系統(tǒng)設計結構
系統(tǒng)設計結構圖中,主控類聚合了文書管理、預案管理、報警管理和收發(fā)文管理4個窗口類。對于這4個功能模塊來說設計結構相同,這里就不再重復敘述,僅對報警管理功能模塊進行詳細介紹。
報警信息管理數(shù)據(jù)類調用報警處置信息變動觀察者類中的報警處置管理虛函數(shù),間接調用報警信息管理界面類中報警處置相關的實現(xiàn)函數(shù),報警信息管理界面類繼承報警處置信息變動觀察者類,是具體實現(xiàn)報警處置信息變動觀察者類中虛函數(shù)操作的類,它利用接口(報警處置信息變動觀察者類中的虛函數(shù))調用報警信息管理界面類中的實現(xiàn)函數(shù)即可以實現(xiàn)報警目標的圖上顯示、報警處置和報警關閉對應界面的更新。
其中,報警處置信息變動觀察者類在觀察者模式中對應觀察者類,它為其所觀察的目標類的改變定義了更新的接口;報警信息管理界面類承擔的是觀察者模式中具體觀察者類的職責,它是報警處置信息變動觀察者類的子類,繼承了父類的接口并實現(xiàn)了這個更新接口,此外它還存儲報警的狀態(tài),利用更新接口使得自身狀態(tài)與其觀察的目標對象狀態(tài)保持一致。報警信息管理數(shù)據(jù)類充當?shù)氖怯^察者模式中具體目標類和目標類二者的角色,它不僅提供對于觀察者的注冊和刪除功能,還提供對注冊的觀察者狀態(tài)進行獲取、設置的功能,當報警狀態(tài)因報警處置(結束報警)或接收報警(啟動報警)而改變時,該類可獲得狀態(tài)并將狀態(tài)的更改通知與之相關的觀察者,完成報警信息管理界面類上的報警狀態(tài)閃爍與否的更新。
雖然采用觀察者模式具有諸如松耦合、易于復用和變更較少等優(yōu)勢,但該模式的使用需要注意如下問題:
①松偶合導致代碼關系不明顯,尤其是模式代碼混入到參與類中來,而產(chǎn)生嚴重的代碼分散問題,降低代碼的可讀性。不過,如果代碼閱讀者熟知觀察者模式則代碼理解上會更容易一些;
②如果一個Subject被大量Observer訂閱的話,在廣播通知的時候可能會有效率問題。畢竟通知只是簡單的遍歷,所以當存在大量觀察者時,這種問題會凸顯出來。這個時候往往意味著設計上可能存在缺陷,需要考慮修改設計,增加多個觀察者接口;
③雖然觀察者模式可以隨時使觀察者知道所觀察的對象發(fā)生了變化,但是觀察者模式?jīng)]有相應的機制使觀察者知道所觀察的對象是怎么發(fā)生變化的。如果需要獲得這種變化,則需要針對變化做出相應的處理,比如在觀察者刷新函數(shù)(Update)中增加變化因素作為參數(shù)。
實踐證明,觀察者設計模式這種設計技術的采用提高了軟件開發(fā)的效率,提高了系統(tǒng)的可重用性和可擴展性,降低了軟件系統(tǒng)中模塊間的耦合度。誠然,設計模式并不是萬能的,但它提供了一種在開發(fā)人員和組織之間共享可使用解決方案的方法,這些解決方案是凝聚了很多設計者積累的知識和經(jīng)驗的最佳實踐。采用適合自己的設計模式將能夠敏捷地構建信息系統(tǒng),更好更快地實現(xiàn)用戶需求。
[1]ERICH G,RICHARD H,RALPH J,et al.Design Patterns:Elements of Reusable Object-Oriented Software[M].李英軍,馬曉星,蔡 敏,等譯.北京:機械工業(yè)出版社,2007.
[2]吳善明,沈建京,劉 輝.淺析Observer模式在GIS軟件設計中的應用[J].計算機工程與設計,2007,28(18):4532-4534.
[3]付登科,郝克剛,葛 瑋.AOP改進觀察者模式——實現(xiàn)關注點的分離[J].計算機應用(自然科學版),2005,25(S1):410-412.
[4]肖計劃,劉海硯,張吉才.設計模式在地圖制圖軟件開發(fā)中的應用[J].測繪工程,2008,17(5):4-7.
[5]王 宇,王 力,李增智,等.面向對象軟件框架中的耦合性及其消解策略的研究[J].小型微型計算機系統(tǒng),2003,24(10):1743-1746.
[6]李 進,師建東,周 琦.一種基于模式的應用網(wǎng)關設計[J].無線電工程,2009,39(9):1-2.