插件系統(tǒng)概述
普通的系統(tǒng),在編譯發(fā)布之后,系統(tǒng)就不允許進(jìn)行更改或擴(kuò)充了,如果要進(jìn)行某個(gè)功能的擴(kuò)充,則必須要修改代碼重新編譯發(fā)布。使用插件可以很好地解決這個(gè)問(wèn)題。
插件概念
首先由開(kāi)發(fā)人員編寫(xiě)系統(tǒng)框架,并預(yù)先定義好系統(tǒng)的擴(kuò)展借口。插件由其他開(kāi)發(fā)人員根據(jù)系統(tǒng)預(yù)定的接口編寫(xiě)的擴(kuò)展功能,實(shí)際上就是系統(tǒng)的擴(kuò)展功能模塊。插件都是以一個(gè)獨(dú)立文件的形式出現(xiàn)。
對(duì)于系統(tǒng)來(lái)說(shuō)并不知道插件的具體功能,僅僅是為插件留下預(yù)定的接口,系統(tǒng)啟動(dòng)的時(shí)候根據(jù)插件的配置尋找插件,根據(jù)預(yù)定的接口把插件掛接到系統(tǒng)中。
優(yōu)勢(shì)
一、系統(tǒng)的擴(kuò)展性大大地加強(qiáng)了。如果我們?cè)谙到y(tǒng)發(fā)布后需要對(duì)系統(tǒng)進(jìn)行擴(kuò)充,就不必重新編譯,只需要增加或修改插件就可以了。
二、有利于模塊化的開(kāi)發(fā)方式。我們可以開(kāi)發(fā)強(qiáng)大的插件管理系統(tǒng),在這樣的一個(gè)插件系統(tǒng)下,我們可以不修改基本系統(tǒng),僅僅使用插件就能構(gòu)造出各種各樣不同的系統(tǒng)。
Eclipse系統(tǒng)架構(gòu)
Eclipse插件系統(tǒng)是非常成功的插件框架結(jié)構(gòu)。網(wǎng)上有很多介紹的文章。這里推薦孟巖的Blog http://www.mengyan.org/blog/archives/2005/09/08/67.html。下面對(duì)Eclipse的框架中的幾點(diǎn)做一個(gè)簡(jiǎn)要的介紹,在后面介紹插件系統(tǒng)架構(gòu)的時(shí)候作為對(duì)比。
插件結(jié)構(gòu)
Eclipse是眾多“可供插入的地方”(擴(kuò)展點(diǎn))和“可以插入的東西”(擴(kuò)展)共同組成的集合體。在我們的生活中,電源接線板就是一種“擴(kuò)展點(diǎn)”,很多“擴(kuò)展”(也就是電線插頭)可以插在它上面。(摘自《Contributing to Eclipse》 Erich Gamma, Kent Beck著)
Eclipse整個(gè)IDE就是一個(gè)插件,他提供了新的擴(kuò)展點(diǎn)供其他插件來(lái)擴(kuò)展。

擴(kuò)展點(diǎn)
可以看到Eclipse的插件結(jié)構(gòu)是由父插件管理子插件,插件之間由擴(kuò)展點(diǎn)連接,最終形成樹(shù)形的結(jié)構(gòu)。
界面呈現(xiàn)
界面呈現(xiàn)由提供擴(kuò)展點(diǎn)的父插件來(lái)決定,比如說(shuō)父插件在菜單上留了擴(kuò)展點(diǎn),那么子插件就可以出現(xiàn)在菜單項(xiàng)上。界面呈現(xiàn)的類型是由提供擴(kuò)展的插件決定。
插件交互
插件之間的交互通過(guò)擴(kuò)展點(diǎn)實(shí)現(xiàn)。父插件調(diào)用子插件實(shí)現(xiàn)的擴(kuò)展點(diǎn)來(lái)觸發(fā)子插件的動(dòng)作。
依賴關(guān)系
配置文件中指定插件運(yùn)行需要依賴的插件,在裝載過(guò)程中會(huì)按照依賴的關(guān)系順序來(lái)裝載。
擴(kuò)展點(diǎn)形成的系統(tǒng)結(jié)構(gòu)
Eclipse中的插件用擴(kuò)展點(diǎn)的機(jī)制連接起來(lái),形成如下圖所示的系統(tǒng)結(jié)構(gòu)。插件必須實(shí)現(xiàn)擴(kuò)展點(diǎn),以此插入到系統(tǒng)中,新增擴(kuò)展點(diǎn)并不是必須的,但只有新增了擴(kuò)展點(diǎn)的插件才可以被別人擴(kuò)展。

懶加載
只有在調(diào)用執(zhí)行動(dòng)作的時(shí)候才會(huì)將真實(shí)的動(dòng)作對(duì)象創(chuàng)建起來(lái)。由于在配置文件中已經(jīng)具備真實(shí)動(dòng)作的一切信息,所以在不裝載插件時(shí),同樣可以在父插件的界面上將擴(kuò)展的功能顯示出來(lái)。
另一個(gè)插件系統(tǒng)
插件結(jié)構(gòu)
插件分為“插件外殼”和“業(yè)務(wù)”兩部分。
其中業(yè)務(wù)部分與插件沒(méi)有任何關(guān)系,按照一般的應(yīng)用程序開(kāi)發(fā)即可。最終提供給插件外殼一個(gè)主要的界面和公布出來(lái)的方法。
插件外殼提供接口供外界調(diào)用。系統(tǒng)和其它插件完全通過(guò)插件外殼和插件進(jìn)行交互。

界面呈現(xiàn)
將每個(gè)插件的界面按照一定形式組織起來(lái)生成整個(gè)系統(tǒng)。界面組織的規(guī)則在配置文件中指定。系統(tǒng)提供可配置的方案。
布局(Layout)
插件按照一定的布局放到整個(gè)系統(tǒng)的界面中。在目前的系統(tǒng)內(nèi)提供了三種布局。
頁(yè)面布局
將插件按照頁(yè)面的形式重疊在一起,插件激活時(shí)將自己所屬的頁(yè)面翻轉(zhuǎn)到最前端。

模塊布局
將插件按照模塊劃分放到同一個(gè)界面顯示。模塊之間用分割條連接。

頁(yè)簽布局
將插件按照頁(yè)簽的形式放到一起。

裝飾(Decorator)
布局指定了插件出現(xiàn)的位置與形式。裝飾可以指定插件出現(xiàn)的方式。
可關(guān)閉裝飾
指定插件出現(xiàn)的部分是否可以關(guān)閉。在普通的模式下,插件可以按照上面的幾種版型出現(xiàn),但這時(shí)的插件界面是不可關(guān)閉的。如果需要增加關(guān)閉功能,可以給插件指定一個(gè)裝飾器。
下面舉一個(gè)在模塊布局中的模塊2上應(yīng)用“可關(guān)閉裝飾”的例子。

布局、裝飾的組合
上面列舉了現(xiàn)有的布局與裝飾,復(fù)雜界面同樣可以有布局與裝飾的組合來(lái)完成。這里的圖式表明將三種布局與裝飾組合的一種情況。

通過(guò)配置文件指定出不同的組合情況就可以完成更多的界面布局了。在更改整個(gè)系統(tǒng)界面布局的時(shí)候只需要修改配置文件,程序并不需要重新發(fā)布。
導(dǎo)航
通過(guò)配置文件裝配好的插件系統(tǒng),界面可能是非常復(fù)雜的。這種情況下要讓用戶找到想要的功能需要用導(dǎo)航器來(lái)呈現(xiàn)系統(tǒng)提供的所用功能。
系統(tǒng)提供的功能就是插件提供的功能的集合,插件提供的功能通過(guò)插件外殼公布出來(lái)。公布的方式依照語(yǔ)言的特性來(lái)定:C#、Java中可以利用反射機(jī)制運(yùn)行公布出來(lái)的方法,Delphi中用RTTI也可以同樣運(yùn)行配置文件中指定的方法。
常見(jiàn)的導(dǎo)航器都可以抽象成樹(shù)形結(jié)構(gòu)。每一個(gè)導(dǎo)航單元映射到一個(gè)用戶需要的功能,每一個(gè)功能對(duì)應(yīng)到具體的插件的某一個(gè)方法。將功能抽象成一個(gè)Action對(duì)象,對(duì)象需要知道它導(dǎo)向的插件和方法名。

可以在上面抽象模型的基礎(chǔ)上實(shí)現(xiàn)任意形式的導(dǎo)航器。可以是菜單項(xiàng),可以是TreeView,也可以是自定義的控件。
交互關(guān)系
系統(tǒng)需要知道插件的操作,插件與插件之間同樣也會(huì)有交互。
將所有的交互關(guān)系用一個(gè)關(guān)系管理器來(lái)存儲(chǔ),插件與外界交互都通過(guò)關(guān)系管理器來(lái)實(shí)現(xiàn)。關(guān)系是在配置文件中指定,分析配置文件的時(shí)候就會(huì)將配置中指定的關(guān)系注冊(cè)到關(guān)系管理器中。
在運(yùn)行期,插件動(dòng)態(tài)從關(guān)系管理器中取得和自己關(guān)聯(lián)的接口。

懶加載
為了節(jié)省用戶資源,需要實(shí)現(xiàn)插件的按需加載,也叫懶加載,只有用到的插件才會(huì)從文件中裝載到內(nèi)存中運(yùn)行。
實(shí)現(xiàn)懶加載需要處理導(dǎo)航器和插件的布局。很多地方需要綁定插件的信息,但這時(shí)插件對(duì)象還不存在。使用代理插件可以解決這個(gè)問(wèn)題。

所有與插件的通信都通過(guò)代理插件對(duì)象來(lái)中轉(zhuǎn)。代理對(duì)象由主框架創(chuàng)建,記錄插件的基本信息。在系統(tǒng)裝載期,綁定到系統(tǒng)中的接口都是代理對(duì)象,當(dāng)外界需要與插件交互,例如顯示、運(yùn)行某個(gè)方法的時(shí)候,由代理來(lái)自動(dòng)裝載真實(shí)的插件,然后將調(diào)用委派給插件來(lái)響應(yīng)。這樣可以讓?xiě)屑虞d過(guò)程對(duì)于系統(tǒng)裝載,插件運(yùn)行是透明的。
架構(gòu)對(duì)比
微內(nèi)核 VS 巨內(nèi)核
Eclipse中的運(yùn)行框架非常小,系統(tǒng)中幾乎所有的都是插件,采用的是微內(nèi)核+插件的形式。在后面介紹的插件架構(gòu)中系統(tǒng)運(yùn)行框架比較復(fù)雜,它包括了界面布局策略、導(dǎo)航、插件代理等職責(zé),可以說(shuō)是巨內(nèi)核+插件的形式。
微內(nèi)核與巨內(nèi)核之爭(zhēng)已經(jīng)有很長(zhǎng)歷史了。在操作系統(tǒng)的概念中尤為突出。網(wǎng)上對(duì)于微內(nèi)核與巨內(nèi)核的討論同樣適用于插件系統(tǒng)。
僅從上面介紹的兩種插件系統(tǒng)來(lái)看,微內(nèi)核的好處在于系統(tǒng)的可擴(kuò)展性強(qiáng),如果你愿意,甚至可以將Eclipse整個(gè)開(kāi)發(fā)環(huán)境都替換掉;巨內(nèi)核的好處在于插件非常簡(jiǎn)單,只需要將業(yè)務(wù)部分用統(tǒng)一的接口公布出來(lái)就可以,在開(kāi)發(fā)具體模塊的時(shí)候可以不用考慮開(kāi)發(fā)的是否是插件。
界面呈現(xiàn)
微內(nèi)核中的界面呈現(xiàn)完全由父插件來(lái)決定,留了什么樣的擴(kuò)展點(diǎn)就可以在界面上以什么樣的形式發(fā)布功能。
巨內(nèi)核中的界面呈現(xiàn)由系統(tǒng)運(yùn)行框架決定,框架支持了幾種顯示的模式。配置文件可以在現(xiàn)有的模式之上隨意組合形成復(fù)雜的界面。在這個(gè)過(guò)程中插件并不關(guān)心自己被放在什么地方,或者以什么形式呈現(xiàn)。
插件關(guān)系
微內(nèi)核中的插件關(guān)系由插件自身來(lái)維持,插件實(shí)現(xiàn)的擴(kuò)展決定了它和父插件之間的交互關(guān)系,新增的擴(kuò)展點(diǎn)決定了它和將來(lái)在它基礎(chǔ)上擴(kuò)展的插件交互的模式。
巨內(nèi)核中的插件關(guān)系由系統(tǒng)框架(關(guān)系管理器)統(tǒng)一管理,插件本身不需要維護(hù)交互信息,只有在需要的時(shí)候才會(huì)從關(guān)系管理器取得。
懶加載
兩種架構(gòu)都可以支持插件的懶加載。基本的思路是一致的。但微內(nèi)核中的插件裝載由父插件來(lái)完成,而巨內(nèi)核中的裝載則直接由系統(tǒng)框架提供的統(tǒng)一代理類來(lái)完成。
posted on 2007-12-26 15:12
前方的路 閱讀(465)
評(píng)論(0) 編輯 收藏 所屬分類:
軟件架構(gòu) 、
軟件思想