構建可擴充套件的應用(一) (轉)

worldblog發表於2007-12-12
構建可擴充套件的應用(一) (轉)[@more@]

構建可擴充套件的應用(一)


Chris Sells  翻譯:Jackal L. Faven


譯註:已對原文進行了部分刪節



  很多開發者都鍾情於化的設計和開發思想。在這種思想的指引下,我們可以很方便的向業已存在的應用中新增新的元件以得到新的功能。他們都期望著使用元件化來構建可在執行期擴充套件的應用。然而,設計階段的元件和最終所使用的元件還是有很大不同的。
  開發者可以使用相當多的現成工具來利用開發應用或是網頁:比如MFC, VC, VB, , , IE3等等。不過很不幸的是,這些工具都不能反過來幫助其他的同類工具使用你所開發出來的應用軟體。這樣的話,即使使用者得到了你的應用的,也只有很少一部分人擁有足夠的資金去得到一份Mircorsoft Developer Studio,並將他所剛買的一個元件嵌入你的應用之中。為了提供可擴充套件性,你需要將自己的應用設計的像小釘板,提供孔洞以便讓使用者能夠釘上他們任何想要釘上的小釘。當然,我們還必須給出這塊釘板的小孔的規格,以使釘板的使用者可以選擇恰當的釘子。
  在平臺下,你有兩種可供選擇的流行方法來提供這種可擴充套件的能力,就是使用動態連線庫(DLL, Dynamic Link Libraries)或使用COM。首先,讓我們來回顧一下所謂的經典方法(即使用動態連線庫),並看看其中蘊藏著那些弊端。然後,再讓我們仔細的研究一下應用COM的方法,再我們研讀完一個例子之後,你就有足夠的能力來構建你自己的可擴充套件應用了。
  你需要組建管理器(Component Category Manager)、包含於最新版的 SDK之中的comcat.h、VC++ 4.2以及ActiveX SDK來編譯本文所使用的例子。
(所有程式均已在Windows 95 OSR2和 4.0下編譯測試透過。)


經典的方法


  你可能已經對這種經典的方法很熟悉了:幾乎與所有的Windows程式設計師都不可避免的要和DLL打交道。一個DLL可以諸如提供封裝,模組化以及其他一些面向的功能優勢,同時還可以在任何時候,被需要它的應用程式載入。當一個DLL被編譯近一個應用之後,它就會將自己的所有介面顯示的暴露出來。正如你所料到的,在Windows下的存在這樣一個很普遍的事實,應用軟體一些的功能被擱置在了其之外的DLL中。
  這種擴充套件方式的經典例子便是很好使但已過時的拼寫檢查。它可以在你的商品化的應用中被廣泛的應用,當有更好的元件出來時,你還可以替換它,以此來增加軟體分發商的在價格戰中的競爭實力。
  這就是所有的好處,我們來看一個獨立的例子:姓名檢查器。
  NameChecker是一個可擴充套件的軟體,它可以允許使用者輸入一系列的姓名,並透過使用者指定的檢查引擎來檢查它們。NameChecker知道該如何找到一個可供利用的檢查引擎,顯示出一系列的描述姓名,同時記住該文件與檢查引擎的關聯情況。
  你可能希望將Mac Wizards和 gurus分開,那麼就請分別使用合適的引擎。這種設計的關鍵在於每種檢查引擎都必須就是建立在相同的、標準化的介面之上。
  使用經典的DLL解決方案,那麼介面看起來應該像是這個樣子:


//NameCheckEngine.h
 BOOL WIN CheckName(LPCSTR szName);
 void WINAPI SuggestName(LPCSTR szName, LPSTR szSuggestion);


任何暴露出這樣的全域性功能的DLL都可以以如下這種方式載入並:
 typedef BOOL (WINAPI *PFNCHECKNAME)(LPCSTR);
 typedef void (WINAPI *PFNSUGGESTNAME)(LPCSTR, LPSTR);
 void CheckNames(const char* pszEngine, char* rgszNames, int nNames)
 {
  HINSTANCE  hinst = LoadLibrary(pszEngine);
  if( hinst )
  {
 PFNCHECKNAME
  pfnCheckName = (PFNCHECKNAME)
  GetProcAddress(hinst, "CheckName");
  PFNSUGGESTNAME
  pfnSuggestName = (PFNSUGGESTNAME)
  GetProcAddress(hinst, "SuggestName");
 //重新遍歷姓名錶
 //呼叫pfnCheckName()和pfnSuggestName()
 FreeLibrary(hinst);
  }
}
  LoadLibrary()和GetProcAddress()正是這種方法的核心所在。許多Windows程式都以這種方式工作——比如 的匯入匯出引擎,Adobe Photoshop和影像過濾,等等。Windows的外殼()也應用這種方式來載入控制皮膚的小程式。更甚於操作本身也使用這一種方式來裝載裝置程式。每一個這種可擴充套件程式都有其獨立的API,並且獨立的尋找已“註冊”的元件。這些都可以包含在一個註冊項中,但也同時意味著一需要把這些DLL放在正確的目錄下,並保證正確的命名規則。
  從理論上講,這種設計沒有任何問題。當一個組建被恰當的加入後,使用者就可以得到一個新的功能。但實際上,會有很多問題暴露出來,其中有:
  大量的GetProcAddress()程式碼
    版本混亂(過後請看看你自己的系統)
    脫離了物件導向編碼方式,而使用的是模組化的API程式設計
    組建隨著應用一起被不正確的註冊進了系統
    必須用特定的語言來實現程式設計介面(通常是C或C++)
  必須用DLL來實現這一程式設計介面(試想一下在上它還可行嗎?)


  唉,有了如此多的問題,別擔心,我們可以慶幸的是我們還有COM方法。


譯註:我將原文的APPLICATION翻譯成了應用,而非軟體。


   



 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-991885/,如需轉載,請註明出處,否則將追究法律責任。

相關文章