外掛程式系統概述
普通的系統,在編譯發布之後,系統就不允許變更或擴充了,如果要進行某個功能的擴充,則必須要修改代碼重新編譯發布。使用外掛程式可以很好地解決這個問題。
外掛程式概念
首先由開發人員編寫系統架構,並預先定義好系統的擴充借口。外掛程式由其他開發人員根據系統預定的介面編寫的擴充功能,實際上就是系統的擴充功能模組。外掛程式都是以一個獨立檔案的形式出現。
對於系統來說並不知道外掛程式的具體功能,僅僅是為外掛程式留下預定的介面,系統啟動的時候根據外掛程式的配置尋找外掛程式,根據預定的介面把外掛程式掛接到系統中。
優勢
一、系統的擴充性大大地加強了。如果我們在系統發布後需要對系統進行擴充,就不必重新編譯,只需要增加或修改外掛程式就可以了。
二、有利於模組化的開發方式。我們可以開發強大的外掛程式管理系統,在這樣的一個外掛程式系統下,我們可以不修改基本系統,僅僅使用外掛程式就能構造出各種各樣不同的系統。
Eclipse系統架構
Eclipse外掛程式系統是非常成功的外掛程式架構結構。網上有很多介紹的文章。這裡推薦孟岩的Blog http://www.mengyan.org/blog/archives/2005/09/08/67.html。下面對Eclipse的架構中的幾點做一個簡要的介紹,在後面介紹外掛程式系統架構的時候作為對比。
外掛程式結構
Eclipse 是眾多“可供插入的地方”(擴充點)和“可以插入的東西”(擴充)共同組成的集合體。在我們的生活中,電源接線板就是一種“擴充點”,很多“擴充”(也就 是電線插頭)可以插在它上面。(摘自《Contributing to Eclipse》 Erich Gamma, Kent Beck著)
Eclipse整個IDE就是一個外掛程式,他提供了新的擴充點供其他外掛程式來擴充。
擴充點
可以看到Eclipse的外掛程式結構是由父外掛程式管理子外掛程式,外掛程式之間由擴充點串連,最終形成樹形的結構。
介面呈現
介面呈現由提供擴充點的父外掛程式來決定,比如說父外掛程式在菜單上留了擴充點,那麼子外掛程式就可以出現在功能表項目上。介面呈現的類型是由提供擴充的外掛程式決定。
外掛程式互動
外掛程式之間的互動通過擴充點實現。父外掛程式調用子外掛程式實現的擴充點來觸發子外掛程式的動作。
依賴關係
設定檔中指定外掛程式運行需要依賴的外掛程式,在裝載過程中會按照依賴的關係順序來裝載。
擴充點形成的系統結構
Eclipse中的外掛程式用擴充點的機制串連起來,形成如所示的系統結構。外掛程式必須實現擴充點,以此插入到系統中,新增擴充點並不是必須的,但只有新增了擴充點的外掛程式才可以被別人擴充。
懶載入
只有在調用執行動作的時候才會將真實的動作對象建立起來。由於在設定檔中已經具備真實動作的一切資訊,所以在不裝載外掛程式時,同樣可以在父外掛程式的介面上將擴充的功能顯示出來。
另一個外掛程式系統外掛程式結構
外掛程式分為“外掛程式外殼”和“業務”兩部分。
其中業務部分與外掛程式沒有任何關係,按照一般的應用程式開發即可。最終提供給外掛程式外殼一個主要的介面和公布出來的方法。
外掛程式外殼提供介面供外界調用。系統和其它外掛程式完全通過外掛程式外殼和外掛程式進行互動。
介面呈現
將每個外掛程式的介面按照一定形式組織起來產生整個系統。介面組織的規則在設定檔中指定。系統提供可配置的方案。
布局(Layout)
外掛程式按照一定的布局放到整個系統的介面中。在目前的系統內提供了三種布局。
頁面配置
將外掛程式按照頁面的形式重疊在一起,外掛程式啟用時將自己所屬的頁面翻轉到最前端。
模組布局
將外掛程式按照模組劃分放到同一個介面顯示。模組之間用分割條串連。
頁簽布局
將外掛程式按照頁簽的形式放到一起。
裝飾(Decorator)
布局指定了外掛程式出現的位置與形式。裝飾可以指定外掛程式出現的方式。
可關閉裝飾
指定外掛程式出現的部分是否可以關閉。在普通的模式下,外掛程式可以按照上面的幾種版型出現,但這時的外掛程式介面是不可關閉的。如果需要增加關閉功能,可以給外掛程式指定一個裝飾器。
下面舉一個在模組布局中的模組2上應用“可關閉裝飾”的例子。
布局、裝飾的組合
上面列舉了現有的布局與裝飾,複雜介面同樣可以有布局與裝飾的組合來完成。這裡的圖式表明將三種布局與裝飾組合的一種情況。
通過設定檔指定出不同的組合情況就可以完成更多的介面布局了。在更改整個系統介面布局的時候只需要修改設定檔,程式並不需要重新發布。
導航
通過設定檔裝配好的外掛程式系統,介面可能是非常複雜的。這種情況下要讓使用者找到想要的功能需要用導航器來呈現系統提供的所用功能。
系統提供的功能就是外掛程式提供的功能的集合,外掛程式提供的功能通過外掛程式外殼公布出來。公布的方式依照語言的特性來定:C#、Java中可以利用反射機制運行公布出來的方法,Delphi中用RTTI也可以同樣回合組態檔案中指定的方法。
常見的導航器都可以抽象成樹形結構。每一個導航單元映射到一個使用者需要的功能,每一個功能對應到具體的外掛程式的某一個方法。將功能抽象成一個Action對象,對象需要知道它導向的外掛程式和方法名。
可以在上面抽象模型的基礎上實現任意形式的導航器。可以是功能表項目,可以是TreeView,也可以是自訂的控制項。
互動關係
系統需要知道外掛程式的操作,外掛程式與外掛程式之間同樣也會有互動。
將所有的互動關係用一個關係管理器來儲存,外掛程式與外界互動都通過關係管理器來實現。關係是在設定檔中指定,分析設定檔的時候就會將配置中指定的關係註冊到關係管理器中。
在運行期,外掛程式動態從關係管理器中取得和自己關聯的介面。
懶載入
為了節省使用者資源,需要實現外掛程式的按需載入,也叫懶載入,只有用到的外掛程式才會從檔案中裝載到記憶體中運行。
實現懶載入需要處理導航器和外掛程式的布局。很多地方需要綁定外掛程式的資訊,但這時外掛程式對象還不存在。使用代理外掛程式可以解決這個問題。
所 有與外掛程式的通訊都通過代理外掛程式對象來中轉。代理對象由主架構建立,記錄外掛程式的基本資料。在系統裝載期,綁定到系統中的介面都是代理對象,當外界需要與外掛程式 互動,例如顯示、運行某個方法的時候,由代理來自動裝載真實的外掛程式,然後將調用委派給外掛程式來響應。這樣可以讓懶載入過程對於系統裝載,外掛程式運行是透明的。
架構對比微核心 VS 巨核心
Eclipse中的運行架構非常小,系統中幾乎所有的都是外掛程式,採用的是微核心+外掛程式的形式。在後面介紹的外掛程式架構中系統運行架構比較複雜,它包括了介面布局策略、導航、外掛程式代理等職責,可以說是巨核心+外掛程式的形式。
微核心與巨核心之爭已經有很長歷史了。在作業系統的概念中尤為突出。網上對於微核心與巨核心的討論同樣適用於外掛程式系統。
僅從上面介紹的兩種外掛程式系統來看,微核心的好處在於系統的可擴充性強,如果你願意,甚至可以將Eclipse整個開發環境都替換掉;巨核心的好處在於外掛程式非常簡單,只需要將業務部分用統一的介面公布出來就可以,在開發具體模組的時候可以不用考慮開發的是否是外掛程式。
介面呈現
微核心中的介面呈現完全由父外掛程式來決定,留了什麼樣的擴充點就可以在介面上以什麼樣的形式發布功能。
巨核心中的介面呈現由系統運行架構決定,架構支援了幾種顯示的模式。設定檔可以在現有的模式之上隨意組合形成複雜的介面。在這個過程中外掛程式並不關心自己被放在什麼地方,或者以什麼形式呈現。
外掛程式關係
微核心中的外掛程式關係由外掛程式自身來維持,外掛程式實現的擴充決定了它和父外掛程式之間的互動關係,新增的擴充點決定了它和將來在它基礎上擴充的外掛程式互動的模式。
巨核心中的外掛程式關係由系統架構(關係管理器)統一管理,外掛程式本身不需要維護互動資訊,只有在需要的時候才會從關係管理器取得。
懶載入
兩種架構都可以支援外掛程式的懶載入。基本的思路是一致的。但微核心中的外掛程式裝載由父外掛程式來完成,而巨核心中的裝載則直接由系統架構提供的統一代理類來完成。