插件系統概述
普通的系統,在編譯發布之后,系統就不允許進行更改或擴充了,如果要進行某個功能的擴充,則必須要修改代碼重新編譯發布。使用插件可以很好地解決這個問題。
插件概念
首先由開發人員編寫系統框架,并預先定義好系統的擴展借口。插件由其他開發人員根據系統預定的接口編寫的擴展功能,實際上就是系統的擴展功能模塊。插件都是以一個獨立文件的形式出現。
對于系統來說并不知道插件的具體功能,僅僅是為插件留下預定的接口,系統啟動的時候根據插件的配置尋找插件,根據預定的接口把插件掛接到系統中。
優勢
一、系統的擴展性大大地加強了。如果我們在系統發布后需要對系統進行擴充,就不必重新編譯,只需要增加或修改插件就可以了。
二、有利于模塊化的開發方式。我們可以開發強大的插件管理系統,在這樣的一個插件系統下,我們可以不修改基本系統,僅僅使用插件就能構造出各種各樣不同的系統。
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整個開發環境都替換掉;巨內核的好處在于插件非常簡單,只需要將業務部分用統一的接口公布出來就可以,在開發具體模塊的時候可以不用考慮開發的是否是插件。
界面呈現
微內核中的界面呈現完全由父插件來決定,留了什么樣的擴展點就可以在界面上以什么樣的形式發布功能。
巨內核中的界面呈現由系統運行框架決定,框架支持了幾種顯示的模式。配置文件可以在現有的模式之上隨意組合形成復雜的界面。在這個過程中插件并不關心自己被放在什么地方,或者以什么形式呈現。
插件關系
微內核中的插件關系由插件自身來維持,插件實現的擴展決定了它和父插件之間的交互關系,新增的擴展點決定了它和將來在它基礎上擴展的插件交互的模式。
巨內核中的插件關系由系統框架(關系管理器)統一管理,插件本身不需要維護交互信息,只有在需要的時候才會從關系管理器取得。
懶加載
兩種架構都可以支持插件的懶加載。基本的思路是一致的。但微內核中的插件裝載由父插件來完成,而巨內核中的裝載則直接由系統框架提供的統一代理類來完成。
posted on 2007-12-26 15:12
前方的路 閱讀(465)
評論(0) 編輯 收藏 所屬分類:
軟件架構 、
軟件思想