,,,
(1. 大慶油田有限責任公司測試技術服務分公司 黑龍江 大慶 163412;2. 東北石油大學電氣信息工程學院 黑龍江 大慶 163318)
相對于大多數的商用軟件來說,測井軟件的需求變化是非常快的。這就要求測井軟件必須能夠及時修改,增添新的功能,適應新的變化,即對其擴展性及復用性提出了非常高的要求。
測井軟件的一個主要功能就是數據采集和控制,當地面系統的硬件板卡改變或增減時,軟件就需要相應的修改。另外,隨著測井項目的不斷增加,軟件功能和要求也會越來越多。同時,隨著操作系統的升級換代,對軟件的兼容性和可移植性也提出了較高的要求。
以上需求的變化,大大增加了測井軟件的開發難度。嚴重時,為了增加某一功能,軟件可能就不得不重新設計。如何適應需求的變化,最大程度的實現軟件復用,已成為軟件人員迫切需要解決的問題。
設計模式[1-4]的概念最早來源于建筑學,由建筑師Alexander提出來的。它是一套被反復使用,經過分類編目的,代碼設計經驗的總結。使用設計模式是為了可重用設計,它可以被用于新的語境中,并為使用者提供一些處理新情況的建議。設計模式使代碼編制真正工程化[5],是軟件工程的基石。
設計模式可以幫助人們復用現有的設計結構和體系結構[6],并且實現起來具有過程簡單,方便的特點。
1)模式名
助記名,一個有助記憶的名稱,將模式中的問題、解決方案以及達到的效果用一(兩)個詞描述出來。應用設計模式,我們可以進行較高的抽象層次設計。模式名除了有助于我們思考之外,還可以使我們更方便的與其他設計者進行設計思想及設計結果的交流。
2)問題
它可能指出了設計中存在現有問題的原因,以及可能產生的后果,也有可能描述了需要增加的設計問題,也有可能描述了一些類或對象結構,它們是導致設計不靈活的主要原因。有時候,問題部分會包括使用模式必須滿足的一系列先決條件。
3)解決方案
描述的是設計的組成部分之間的相互關系及各自的職責和協作方式。模式就好比是一個設計模板,可應用于多種不同場合,所以解決方案并不是一個特定而具體的設計或實現,它是對設計問題的抽象描述,以及指出怎樣用一個具有一般意義的元素組合(類或對象組合)來解決這個問題。
4)效果
采用設計模式后的應用效果及使用模式設計過程中應權衡的問題。它包括模式效果和軟件效果兩個方面[7-9]。在進行設計決策時,模式效果雖然不常被提到,但它在評價設計選擇和理解使用模式的代價及好處等方面卻具有重要意義。一般情況下,軟件效果表述的是語言和實現問題,是在時間和空間的衡量。
設計模式通常分為兩類[10,11]:一是按照設計目的不同進行分類,該類模式主要以具體完成的工作作為分類標準;二是按照處理范圍不同進行分類,該類模式主要以用于類還是用于對象實例作為分類標準。按照第一種分類方式,設計模式可分為創建模式、結構模式和行為模式三大類。按照第二種分類方式,設計模式可分為類模式和對象模式兩大類。具體設計模式分類如表1所示。

表1 設計模式分類表
各種模式均有其自身特點和適用范圍,所以在選取模式前應充分了解模式的內涵及側重點,發掘出不同模式的適用規律[12,13]。
選擇合適的軟件設計模式通常需要考慮以下幾個方面:
1)熟練掌握各種設計模式的處理范圍;
2)瀏覽模式的意圖部分;
3)研究模式之間如何相互聯系;
4)將目的相同模式進行對比研究;
5)明確重新進行設計的意圖;
6)明確設計中的可變元素。
一般的選擇步驟如下:
1)對所要解決的問題進行抽象,并劃分適當的類型;
2)根據問題類型選擇適合的設計模式;
3)規劃問題和匹配模式;
4)對選取的模式進行變體,即對模式的原始結構進行修改和擴展,以解決具體問題;
5)設計并細化所需的軟件體系結構;
6)對設計質量進行度量。
測井軟件的用戶需求是變化的,因而軟件的修改是不可避免的。需求的變化主要表現在測井地面系統硬件的改動及測井項目的增加,這些變化因素在軟件的設計中必須重點考慮。針對上述實際情況,在軟件設計過程中采用了設計模式[14,15],則主要是因為其具有適應需求的變化的特點。此外,由于設計模式的引入,使得測井軟件系統不僅具有更好的可復用性,其擴展性和維護性也變得更加容易。
測井軟件的一項主要功能是實現實時的數據采集。這就要求軟件與具體的采集板卡發生交互,即下傳控制指令,上傳采集數據。另外,實時采集軟件一般采用多線程設計,使得多個線程可能同時操作同一采集板卡或一個線程控制多個采集板卡。對于測井軟件來說,地面硬件系統具有唯一性,但對于硬件系統自身來講,它所包含的采集板卡的數量和功能是可變的。
下面以超越地面系統硬件接口組件設計為例,介紹一下如何將設計模式應用于測井軟件的設計中,以提高軟件質量。
定義: 保證一個類僅有一個實例,并提供一個訪問它的全局訪問點。適用于在一個系統要求一個類只有一個實例時才應當使用單例模式。
這個唯一實例應該是通過子類化可擴展的,并且客戶應該無需更改代碼就能使用一個擴展的實例時。
優點:對唯一實例的受控訪問;自行實例化并向整個系統提供這個實例。單件模式取代了全局對象,降低了代碼耦合度,便于程序修改和維護。
針對超越地面系統硬件的唯一性,以前的測井軟件設計常常將硬件接口對象定義為一個全局變量,而全局變量是程序員心中永遠的痛。主要問題包括:
1)變量名沖突,增加管理成本。
2)耦合度增加。
3)單個實例問題。全局變量不能阻止程序員定義一個類的多個對象實例。在一個多人參與、并行開發的大型項目中,這也會增加很多管理上的負擔。
4)初始化順序。全局變量不可能保證相互之間遵循特定的初始化順序,這完全由編譯器決定。
5)多線程訪問。當多個并發的線程都需要訪問某些全局變量時,我們必須使用各種同步機制,小心地保護這些全局變量,以免陷入并發沖突的泥潭。
設計模式中的單件模式就很好地解決了此類問題,它即保證了對象的唯一性,也避免了全局變量帶來的問題。單件模式就是以一個類只有一個對象實例為設計目的,并提供一個訪問該對象實例的全局訪問點。程序員不能通過類的構造函數獲得對象實例(因為構造函數聲明為private或protected類型),但可以從該類提供的靜態成員函數得到該類唯一的對象實例指針或引用。從某種意義上說,我們可以把這個對象實例看做一個隱藏在單件類內部的“隱式全局變量”。因此在超越測井軟件的硬件接口設計中采用了單件模式,程序部分代碼如下:
class CExceedHard : public CHardInterface
{
private:
CExceedHard(void);
public:
~CExceedHard(void);
static CHardInterface* GetInstance(void);
static void DelInstance(void);
}
定義:定義一個創建對象的抽象類(接口),但是卻讓子類來決定具體實例化哪一個類。當一個類無法預料要創建哪種類的對象或是一個類需要由子類來指定創建的對象時,我們就需要用到該模式了。工廠方法模式可以根據不同的條件產生不同的實例,但這些不同的實例通常是屬于相同的類型,并具有共同的父類。
優點:當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體對象以及一個具體工廠對象,原有工廠對象不需要進行任何修改,也不需要修改客戶端,很好的符合了“開放-封閉”原則。
超越地面系統硬件接口組件中聚合多個采集板卡對象,這些采集板卡對象是否都需要創建,還是選擇性的創建幾個,是由組件根據測井項目的需要來動態創建的。硬件接口組件的調用者不知道,也無需知道具體要創建哪些采集板卡對象。這種方式可以更好地適應未來采集板卡數量的改變及功能的變化。
設計模式中的工廠方法模式可以很好地解決此類問題。工廠方法模式以定義一個用于創建對象的接口為設計目的,讓子類決定實例化哪一個類,將實例化延遲到其子類。對應的問題范疇就是一個類需要實例化另一個類的派生類,但不知道具體是哪個派生類。工廠方法模式允許派生類來做出決定。該模式在定義框架的過程中很常用。這是因為框架存在于一個抽象的層次上。通常,它們不知道,而且也不應該關心特定對象的實例化。它們需要將特定對象的決策推遲框架的用戶。
在超越地面系統硬件接口組件設計中,就是采用工廠方法模式來動態創建需要的板卡對象。即根據測井項目需要的測量通道來動態創建含有此通道的采集板卡對象,而無需由程序員在代碼中明確創建某一類型的采集板卡對象。這種實現方式也體現出了設計模式的設計原則和理念,即針對接口編程,而不要針對實現編程,根本的意圖是適應需求變化。程序的部分代碼如下:
short CExceedHard::AddChannel(CString strName, UINT uChannelSize, UINT uBufferLen, DataType iDataType)
{
CBDChannel* pChannel = new CBDChannel(strName, uChannelSize, uBufferLen);
if(pChannel != NULL)
{
BDChannelInfo* pChInfo = NULL;
for(int i=0; i { pChInfo = (BDChannelInfo*)m_inherentChannelInfoList.GetAt(i); if(pChInfo != NULL) { if(strName == pChInfo->strChannelName) { CString strBoardName = pChInfo->strBoardName; if(strBoardName == _T("SC58301A")) pBoard = new CBD58301A(); else if(strBoardName == _T("SC58112")) pBoard = new CBD58112(); else if(strBoardName == _T("SC58114")) pBoard = new CBD58114(); if(pBoard != NULL) { m_usedBoardList.Add(pBoard); return HD_SUCCESS;}}}}}} 采用該種設計的優點:當系統擴展需要添加新的產品對象時,僅僅需要添加一個具體對象以及一個具體工廠對象,原有工廠對象不需要進行任何修改,也不需要修改客戶端,很好的符合了“開放-封閉”原則。 設計模式既簡單又復雜。使用設計模式要求我們添加更多的類,進行更多的設計工作,這是設計模式復雜的一面。它提醒我們,設計模式只應對變化或可能變化的部分使用,對于不變的部分濫用就會造成“過度設計”。由于超越地面系統的測井軟件具有用戶需求變化,軟件修改不可避免等特點。因此,在軟件設計過程中采用設計模式,此外,由于設計模式的引入,使得測井軟件系統不僅具有更好的可復用性,其擴展性和維護性也變得更加容易。實現了面對變化的需求時,我們只需要修改很少的代碼,就可以滿足新的需求,這是設計模式簡單的一面,它可以大幅度簡化我們后續的開發和維護工作。 設計模式最根本的意圖就是適應需求變化,這一點正是測井軟件急需解決而不好解決的問題。另外,設計模式可以有效地提高軟件的設計和代碼復用性,便于成果的繼承,事半功倍。因此,學習運用設計模式是開發高質量測井軟件的必由之路,前景廣闊。 [1] GAMMA E.設計模式—可復用面向對象軟件的基礎[M].李英軍,譯.北京:機械工業出版社,2000:55-75. [2] JACOBSON I.The unified modeling language development process [M].Boston: Addison Wesley, 1998:141-152. [3] MIKKONEN T.Formalizing design patterns[A].Proceedings of International Conference on Software Engineering [C].New York: IEEE Computer Society Press, 1998:115-124. [4] GAMMA E. Design patterns: elements of reusable object-oriented systems[M] . Boston: Addison Wesley,1995:75-90. [5] 萬劍怡,薛錦云.使用規范匹配實現設計模式的自動獲取[J].小型微型計算機系統,2002,23(3):326-329. [6] 張世博,周樹杰,閔艷.JAVA程序開發中的設計模式[J].微型電腦應用, 2002, 18(9): 45-47. [7] 鐘茂生,王明文.軟件設計模式及其使用[J].計算機應用,2002,22(8):32-35. [8] 廖志剛,李增智.設計模式在系統中的應用[J].計算機工程與應用,2002, (12): 7-10. [9] GAMMA E. Design patterns elements of reusable object-oriented software[M].北京:機械工業出版社,2002:124-130. [10] 童立,馬遠良.設計模式在基于組件的框架設計中的應用[J].計算機工程與應用,2002, (17): 123-128. [11] ALUR D.Core J2EE patterns[M]. 北京:機械工業出版社,2002:89-120. [12] ALAN SHALLOWAY & JAMES R. TROTT.設計模式精解[M].清華大學出版社,2004,12:1-238. [13] 王詠武 王詠剛.道法自然-面向對象實踐指南[M].電子工業出版社,2004:10,1-432. [14] 劉海巖.設計模式及其在軟件設計中的應用研究[J].西安交通大學學報,2005,39(10):1043-1047. [15] ECKEL B.Java 編程思想(第二版)[M].侯捷,譯.北京:機械工業出版社,2002:5-120.3 結束語