構建可擴充套件的應用(一) (轉)
構建可擴充套件的應用(一)
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 如何構建可控,可靠,可擴充套件的 PWA 應用套件
- Django與微服務架構:構建可擴充套件的Web應用Django微服務架構套件Web
- 如何構建一個優雅擴充套件套件
- 讀構建可擴充套件分散式系統:方法與實踐15可擴充套件系統的基本要素套件分散式
- VSCode擴充套件應用VSCode套件
- 讀構建可擴充套件分散式系統:方法與實踐09可擴充套件資料庫基礎套件分散式資料庫
- Django內建許可權擴充套件案例Django套件
- 實用的可選項(Optional)擴充套件套件
- 使用 Python 構建可擴充套件的社交媒體情感分析服務Python套件
- 可擴充套件性套件
- blog-engine-09-nuxt 構建快速、SEO友好和可擴充套件的Web應用程式變得輕鬆UX套件Web
- DoorDash使用 Kafka 和 Flink 構建可擴充套件的實時事件處理Kafka套件事件
- 構建高可用性、高效能和可擴充套件的Zabbix Server架構套件Server架構
- [譯] 構建高效能和可擴充套件性 Node.js 應用的最佳實踐 [第 3/3 部分]套件Node.js
- easyui應用(四)--- easyui擴充套件UI套件
- 並查集擴充套件應用並查集套件
- 使用 Zephir 輕鬆構建 PHP 擴充套件PHP套件
- 使用 Postgres 的全文搜尋構建可擴充套件的事件驅動搜尋架構套件事件架構
- 簡要剖析:可擴充套件的微服務架構套件微服務架構
- 谷歌的三大可擴充套件核心架構谷歌套件架構
- 使用 .NET Core 構建可擴充套件的實時資料處理系統套件
- 基於 Golang 構建高可擴充套件的雲原生 PaaS(附 PPT 下載)Golang套件
- Caddy-用Go寫的新一代可擴充套件WebServerGo套件WebServer
- ?用Chrome擴充套件管理器, 管理你的擴充套件Chrome套件
- SQL_Postgresql-一些擴充套件和應用SQL套件
- 使用View modification擴充套件SAP Fiori應用的一個案例View套件
- 編寫可擴充套件程式套件
- 如何使用Zebee構建高度可擴充套件的分散式工作流中介軟體?套件分散式
- plain framework的實際應用和擴充套件AIFramework套件
- Apache Cassandra——可擴充套件微服務應用程式的持久資料儲存Apache套件微服務
- WPF如何封裝一個可擴充套件的Window封裝套件
- 【軟體架構篇】常見可擴充套件模式架構套件模式
- Flutter 應用程式建立一個擴充套件皮膚列表Flutter套件
- 讀構建可擴充套件分散式系統:方法與實踐08微服務套件分散式微服務
- chrome擴充套件應用開發快速科普Chrome套件
- PHP擴充套件開發就是一個自己的PHP擴充套件PHP套件
- 讀構建可擴充套件分散式系統:方法與實踐11強一致性套件分散式
- kotlin 擴充套件(擴充套件函式和擴充套件屬性)Kotlin套件函式
- dubbo是如何實現可擴充套件的?套件