物件導向的思想難以適應這種分布式軟體模型,於是組件化程式設計思想得到了迅速的發展。按照組件化的程式設計的思想,複雜的應用程式被設計成一些小的,功能單一的組件模組,這些組件模組可以運行在同一台機器上,也可以運行在不同的機器上。為了實現這樣的應用軟體,組建程式和組建程式之間需要一些極為細緻的規範, 只有組件程式遵守了這些共同的規範,然間系統才能正常運行。為此,OMG和Microsoft分別提出了CORBA(Common Object Request BreakerArchitecture)和COM(Component Objectmodel)標準,目前CORBA模型主要應用於UNIX作業系統平台上,而COM 則主要應用於Microsoft Windows作業系統平台上。 在COM標準中,一個組件程式也被稱為一個模組,它可以是一個動態串連庫(DLL), 被稱為進程內組件(in-of-processcomponent)也可以是一個可執行程式(EXE),被稱為進程外組件(out-of-process component). COM對象是建立在二進位可執行代碼級的基礎上,而C++等語言中的對象是建立在原始碼級基礎上的,因此COM對象是語言無關的。這一特性使用不同程式設計語言開發的組件對象進行互動成為可能。在MicrosoftWindows系統平台上,COM技術被應用於系統的各個層次,從底層的COM對象管理到上層的應用程式互動都用到了COM標準。 概述
COM既提出了組件之間進行互動的規範,也提供了實現互動的環境,因為組件對象之間互動的規範不依賴於任何特定的語言,所以COM也可以是不同語言協作開發的一種標準。OLE技術以COM規範為基礎,OLE充分發揮了COM標準的優勢,使Windows作業系統上的應用程式具有極強的可互動性。如果沒有OLE的支援,Windows作業系統則會遜色很多。 但是,COM規範並不局限於OLE技術,實際上,OLE技術只是COM的一個應用而已,這幾年,OLE技術在進行網路互連是顯示出了很大的局限性,而COM則表現出了極強的適應能力。COM標準包括規範和實現兩大部分,規範部分定義了組件和組件之間通訊的機制,這些規範不依賴於任何特定的語言和作業系統,只要按照該規範,任何語言都可以使用; COM標準的實現部分是COM庫,COM庫為COM規範的具體實現提供了一些核心服務。 COM是面對對象的軟體模型,因而對象是他的基本要素之一。類似於C++中對象的概念,對象是某個類(class)的一個執行個體;而類則是一組相關的資料和功能組和在一起的一個定義。使用對象的應用(或另一個對象)成為客戶,有時也成為對象的使用者。 介面是一組邏輯上相關的函數集合,其函數也被稱為介面成員函數。對象通過介面成員函數為客戶提供各種形式的服務。 在COM模型中,對象本身對於客戶來說是不可見的,客戶請求服務時,只能通過介面進行。每一個介面都由一個128位的通用唯一識別碼(GUID,Globally UniqueIdentifier)來標識。客戶通過GUID獲得介面的指標,在通過介面指標,客戶就可以調用其相應的成員函數。 一般來說,介面是不變的,只要客戶期望的介面在組建對象中還存在,它就可以繼續使用該介面所提供的服務。對象可以支援多個介面,因此對組件對象的升級可通過增加介面的辦法實現,這樣得到的新介面可以不影響老介面的使用。 客戶如何來標識COM對象呢?與介面類似,每個對象也用一個128位GUID來標識,稱為CLSID(classidentifier,類別識別項或類ID),用CLSID標識對象可以保證(機率意義上)在全球範圍內的唯一性。
只要系統中含有這類COM對象的資訊,並包括COM對象所在的模組檔案(DLL或EXE檔案)以及COM對象在代碼中的進入點,客戶程式就可以由此CLSID來建立COM對象。 那麼客戶怎麼使用COM對象所提供的服務呢?客戶獲得的又是什麼呢?實際上,客戶成功建立對象後,它得到的是一個指向對象某個介面的指標,因為COM對象至少實現一個介面,所以客戶就可以調用該介面提供的所有服務。但是COM對象可以有自己的狀態,正是這種狀態才使客戶感覺到COM對象的存在。如果客戶同時擁有兩個相同CLSID的對象,則兩個對象可以有不同的狀態,客戶完全不必關心COM對象是怎麼實現的,以及兩個對象的狀態資料之間有什麼關係(數組或者鏈表)。當然,COM對象也可以是無狀態的,這種COM對象以提供功能服務為主,可以用來代替傳統的API函數介面,使得API更為有序,組織層次性更強。 COM本身除了規範之外,也有實現的部分,其中包括一些核心的系統級代碼,也正是這部分核心代碼,才使得對象和客戶之間可通過介面在二進位代碼級進行互動 。在Microsoft Windows作業系統環境下,這些庫以.dll檔案的形勢存在,其中包括以下內容:(1) 提供了少量的API函數實現客戶和服務端COM應用的建立過程。在用戶端,主要是一些建立函數;而在伺服器端,提供一些對象的訪問支援。(2) COM通過註冊表尋找本機伺服器即EXE程式,以及程式名與CLSID的轉換等。(3) 提供了一些標準的記憶體控制方法,使應用控制進程中記憶體的分配。
COM庫一般不在應用程式層實現,而在作業系統層次上實現,因此一個作業系統只有一個COM庫實現。而且COM庫的實現必須依賴於具體的系統平台,尤其是系統底層的一些標準。COM庫可以保證所有的組件按照統一的方式進行互動操作,而且它使我們在編寫COM應用時,可以不用編寫為進行COM通訊而必需的大量基礎代碼,而是直接利用COM庫提供的API進行編程,從而大大加快了開發的速度。例如,現在COM庫的版本都支援遠程組件即分布式COM,我們不用編寫任何網路或者RPC(remote procedure call)的代碼,就可以實現在網路上進行程式之間的通訊。 如果我們用物件導向語言來實現COM對象,則很自然可以用類類定義對象。在C語言中,對象的概念可能變成一個邏輯概念,如果兩個對象同時存在,則在介面實現中必須明確知道所進行的操作是針對哪個對象的,這個過程可由COM介面的定義保證。COM規範使用GUID來標識COM對象的思想源於OSF(Open SoftwareFoundation)採用的UUID(Universallz Unique Identifier),UUID被定義為DCE(Distributed Computing Environment)的一部分,主要用於表識RPC通訊的雙方。除了封裝性和重用性,C++對象還有一個重要特性是多態性。正是C++對象的多態性,才體現了C++語言用類描述事物的高度抽象的特徵;COM對象也具有多態性,但這種多態性需要通過COM對象所具有的介面才能體現出來,就像C++對象的多態性需要通過其(virtual)函數才能體現一樣。 從API到COM介面假如我們要實現一個文書處理應用系統,它需要一個查字典的功能,按照組件化程式設計的方法,自然應該把查字典的功能放到一個組件(.dll)程式中實現。如果以後字典程式的尋找演算法或者字典庫改變了,只要應用程式和組件之間的介面不變,則新的組件程式仍然可以被應用系統使用。這就是採用組件程式帶來的靈活性。 為了把應用系統和組件程式串連起來,又能使它們協同工作,最簡單的做法就是先定義一組查字典的函數,而且這組函數儘可能一般化,不要加入特定的與字典庫相關的知識。