• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            woaidongmao

            文章均收錄自他人博客,但不喜標題前加-[轉貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評論 - 661, 引用 - 0
            數據加載中……

            插件系統構建

            插件系統概述

            普通的系統,在編譯發布之后,系統就不允許進行更改或擴充了,如果要進行某個功能的擴充,則必須要修改代碼重新編譯發布。使用插件可以很好地解決這個問題。

            插件概念

            首先由開發人員編寫系統框架,并預先定義好系統的擴展借口。插件由其他開發人員根據系統預定的接口編寫的擴展功能,實際上就是系統的擴展功能模塊。插件都是以一個獨立文件的形式出現。

            對于系統來說并不知道插件的具體功能,僅僅是為插件留下預定的接口,系統啟動的時候根據插件的配置尋找插件,根據預定的接口把插件掛接到系統中。

            優勢

            一、系統的擴展性大大地加強了。如果我們在系統發布后需要對系統進行擴充,就不必重新編譯,只需要增加或修改插件就可以了。

            二、有利于模塊化的開發方式。我們可以開發強大的插件管理系統,在這樣的一個插件系統下,我們可以不修改基本系統,僅僅使用插件就能構造出各種各樣不同的系統。

            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就是一個插件,他提供了新的擴展點供其他插件來擴展。

            clip_image001

            擴展點

            可以看到Eclipse的插件結構是由父插件管理子插件,插件之間由擴展點連接,最終形成樹形的結構。

            界面呈現

            界面呈現由提供擴展點的父插件來決定,比如說父插件在菜單上留了擴展點,那么子插件就可以出現在菜單項上。界面呈現的類型是由提供擴展的插件決定。

            插件交互

            插件之間的交互通過擴展點實現。父插件調用子插件實現的擴展點來觸發子插件的動作。

            依賴關系

            配置文件中指定插件運行需要依賴的插件,在裝載過程中會按照依賴的關系順序來裝載。

            擴展點形成的系統結構

            Eclipse中的插件用擴展點的機制連接起來,形成如下圖所示的系統結構。插件必須實現擴展點,以此插入到系統中,新增擴展點并不是必須的,但只有新增了擴展點的插件才可以被別人擴展。

            clip_image002

            懶加載

            只有在調用執行動作的時候才會將真實的動作對象創建起來。由于在配置文件中已經具備真實動作的一切信息,所以在不裝載插件時,同樣可以在父插件的界面上將擴展的功能顯示出來。

            另一個插件系統

            插件結構

            插件分為插件外殼業務兩部分。
            其中業務部分與插件沒有任何關系,按照一般的應用程序開發即可。最終提供給插件外殼一個主要的界面和公布出來的方法。
            插件外殼提供接口供外界調用。系統和其它插件完全通過插件外殼和插件進行交互。

            clip_image003

            界面呈現

            將每個插件的界面按照一定形式組織起來生成整個系統。界面組織的規則在配置文件中指定。系統提供可配置的方案。

            布局(Layout

            插件按照一定的布局放到整個系統的界面中。在目前的系統內提供了三種布局。

            頁面布局

            將插件按照頁面的形式重疊在一起,插件激活時將自己所屬的頁面翻轉到最前端。

            clip_image004

            模塊布局

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

            clip_image005

            頁簽布局

            將插件按照頁簽的形式放到一起。

            clip_image006

            裝飾(Decorator

            布局指定了插件出現的位置與形式。裝飾可以指定插件出現的方式。

            可關閉裝飾

            指定插件出現的部分是否可以關閉。在普通的模式下,插件可以按照上面的幾種版型出現,但這時的插件界面是不可關閉的。如果需要增加關閉功能,可以給插件指定一個裝飾器。

            下面舉一個在模塊布局中的模塊2上應用可關閉裝飾的例子。

            clip_image007

            布局、裝飾的組合

            上面列舉了現有的布局與裝飾,復雜界面同樣可以有布局與裝飾的組合來完成。這里的圖式表明將三種布局與裝飾組合的一種情況。

            clip_image008

            通過配置文件指定出不同的組合情況就可以完成更多的界面布局了。在更改整個系統界面布局的時候只需要修改配置文件,程序并不需要重新發布。

            導航

            通過配置文件裝配好的插件系統,界面可能是非常復雜的。這種情況下要讓用戶找到想要的功能需要用導航器來呈現系統提供的所用功能。
            系統提供的功能就是插件提供的功能的集合,插件提供的功能通過插件外殼公布出來。公布的方式依照語言的特性來定:C#Java中可以利用反射機制運行公布出來的方法,Delphi中用RTTI也可以同樣運行配置文件中指定的方法。

            常見的導航器都可以抽象成樹形結構。每一個導航單元映射到一個用戶需要的功能,每一個功能對應到具體的插件的某一個方法。將功能抽象成一個Action對象,對象需要知道它導向的插件和方法名。

            clip_image009

            可以在上面抽象模型的基礎上實現任意形式的導航器。可以是菜單項,可以是TreeView,也可以是自定義的控件。

            交互關系

            系統需要知道插件的操作,插件與插件之間同樣也會有交互。

            將所有的交互關系用一個關系管理器來存儲,插件與外界交互都通過關系管理器來實現。關系是在配置文件中指定,分析配置文件的時候就會將配置中指定的關系注冊到關系管理器中。
            在運行期,插件動態從關系管理器中取得和自己關聯的接口。

            clip_image010

            懶加載

            為了節省用戶資源,需要實現插件的按需加載,也叫懶加載,只有用到的插件才會從文件中裝載到內存中運行。

            實現懶加載需要處理導航器和插件的布局。很多地方需要綁定插件的信息,但這時插件對象還不存在。使用代理插件可以解決這個問題。

            clip_image011

            所有與插件的通信都通過代理插件對象來中轉。代理對象由主框架創建,記錄插件的基本信息。在系統裝載期,綁定到系統中的接口都是代理對象,當外界需要與插件交互,例如顯示、運行某個方法的時候,由代理來自動裝載真實的插件,然后將調用委派給插件來響應。這樣可以讓懶加載過程對于系統裝載,插件運行是透明的。

            架構對比

            微內核 VS 巨內核

            Eclipse中的運行框架非常小,系統中幾乎所有的都是插件,采用的是微內核+插件的形式。在后面介紹的插件架構中系統運行框架比較復雜,它包括了界面布局策略、導航、插件代理等職責,可以說是巨內核+插件的形式。

            微內核與巨內核之爭已經有很長歷史了。在操作系統的概念中尤為突出。網上對于微內核與巨內核的討論同樣適用于插件系統。

            僅從上面介紹的兩種插件系統來看,微內核的好處在于系統的可擴展性強,如果你愿意,甚至可以將Eclipse整個開發環境都替換掉;巨內核的好處在于插件非常簡單,只需要將業務部分用統一的接口公布出來就可以,在開發具體模塊的時候可以不用考慮開發的是否是插件。

            界面呈現

            微內核中的界面呈現完全由父插件來決定,留了什么樣的擴展點就可以在界面上以什么樣的形式發布功能。

            巨內核中的界面呈現由系統運行框架決定,框架支持了幾種顯示的模式。配置文件可以在現有的模式之上隨意組合形成復雜的界面。在這個過程中插件并不關心自己被放在什么地方,或者以什么形式呈現。

            插件關系

            微內核中的插件關系由插件自身來維持,插件實現的擴展決定了它和父插件之間的交互關系,新增的擴展點決定了它和將來在它基礎上擴展的插件交互的模式。

            巨內核中的插件關系由系統框架(關系管理器)統一管理,插件本身不需要維護交互信息,只有在需要的時候才會從關系管理器取得。

            懶加載

            兩種架構都可以支持插件的懶加載。基本的思路是一致的。但微內核中的插件裝載由父插件來完成,而巨內核中的裝載則直接由系統框架提供的統一代理類來完成。

             

             

             

             

             

             

            ========================================================================================================

            ========================================================================================================

             

            一切都是為了更加簡單。

            從函數到函數庫,然后到類,然后到插件,都是因為我們的軟件系統日益復雜,人腦畢竟有限,不能同時處理那么多的信息量,所以采用分而治之的方法來管理。
            今年已經研究了一年的插件系統,從最開始的懵懵懂懂到現在能有些經驗和大家分享,這個過程本身就是很有意思的。

            最開始系統中有了十幾個插件,經過幾個月的慢慢發展,到了大幾十個,甚至上百個,這個數量就有些令人頭暈了。不過更加麻煩的還不是這近百個插件組裝而成的系統,而是某一個插件系統需要調用另外的一個或多個插件系統。這樣的話,插件的數量就在100的基數上開始翻倍。

            如何做插件系統中的整合成了一個緊急的課題。

            一、插件系統基本結構

            前面寫過一篇文章,說到了插件系統中的微內核與巨內核之分。不過不管是哪一種,任何一個系統都需要有一個啟動點,只不過對于插件系統中的啟動步驟來說,它是一個通用,并且和具體業務無關的獨立模塊。

            可以按照下面的圖示來簡單理解插件系統:

            clip_image012

            圖中的Launcher是插件系統的啟動模塊,EntryPoint是系統的入口點,作為一個接口給Launcher調用。啟動模塊通過EntryPoint將系統運行起來。系統中的插件相互協作滿足用戶的需要。

            二、開始集成

            上面的圖將一個插件系統的基本原素描繪出來了。在具體的項目中,這樣的一個插件系統中插件的數量可能多達上百個。當兩個項目組都在開發各自的產品,項目組A需要將項目組B開發的系統集成到自己的系統中時,就要開始考慮集成的問題了。

            系統中的插件之間存在父子關系,任何一個插件都可以作為另外一個插件的子插件存在。

            如果將系統B作為系統A中某一個插件的子插件是不是就可以解決集成問題了呢?——不錯,一個簡單但實用的解決方法。

            可以將插件系統考慮成一個函數庫,函數庫中的幾百個函數相互協作完成一系列復雜的功能。現在我們需要在自己寫的函數中包含上面函數庫中的所有功能怎么辦,簡單的做法是將函數庫中的某個入口函數作為子函數調用就可以了。

            下面介紹的集成方案基本上就是這個思路。

            三、插件系統集成解決方案

            clip_image013

            3.1 EntryPointEndpoint

            EntryPoint是插件系統的啟動模塊調用系統功能的接口,這個接口是非常簡單的,很多時候僅有一個Run方法,直接對應到用戶的雙擊打開程序的操作。

            在系統A中要調用系統B時,顯然一個簡單的Run方法不能滿足要求,這里另外提出一個系統的入口點(端點)Endpoint

            兩者的區別在于,EntryPoint對應到Launcher的啟動過程,參數簡單;Endpiont對應到其他系統的交互過程,參數復雜,需要通過Endpoint傳遞其他系統需要的信息。

            3.2 BUS

            有了每個系統的端點,還需要將這些端點組合起來,保證插件系統之間的相互通信。類似于電腦中的總線概念。一旦每個系統的Endpoint掛接到了總線上,插件系統就可以通過總線查找到自己需要交互的其他插件系統了。

            這里的總線用關系管理器來實現。因為Endpoint在插件系統中也是作為一個插件存在,這個插件的職責就是和外界交互。關系管理器可以處理任何插件之間的交互,盡管插件并不在同一個系統中。

            3.3 Linker

            在系統A中呈現系統B的功能有多種表現形式,比如說在系統A的某個地方放上一個Button,點擊后系統B出現;或者在系統A中放上一個頁簽,和一般功能并列將系統B呈現在系統A中。不管怎樣呈現,可以將系統B看作系統A的一個插件。這個插件就是圖中的Linker

            Linker是系統B的一個代理插件,它本身并沒有實現業務,只是將與系統B的交互以插件的形式呈現在系統A中。Linker通過總線找到對應的插件系統并將它啟動,同時負責與它的交互。

            四、適配器模式

            Endpoint用的是Adapter的思想,將自身系統的功能以規定好的交互方式發布到總線上,這樣其他插件系統才能與之進行交互。這種方法在系統的集成中用得非常多,已經從設計模式上升到了架構模式的層次。

            有了這種適配器的方式,不僅僅是插件系統可以集成,甚至非插件系統同樣也可以集成到插件系統中來。所作的就是需要給非插件系統提供一個Adapter插件。對于其他插件系統來說,這個非插件系統在BUS的表現也和插件系統沒有差別了。

            clip_image014

            五、說時容易做時難

            上面提出了一種插件系統的集成方案,目前正在逐步的嘗試,過程中還遇到了一些細節上的問題,今后等我慢慢整理出來再和大家分享。

            現在只是做了插件系統與插件系統之間的集成,雖然從理論上說,插件系統與非插件系統的集成也同樣可行,不過目前還沒有實踐,不敢妄下定論。等有了機會再好好研究一下這方面的內容。如果哪位朋友有一些好的經驗愿意分享,在下洗耳恭聽:)

             

             

             

             

            ========================================================================================================

            ========================================================================================================

            插件可以封裝一定的業務,同樣控件也具有封裝性。

            可以說控件的出現大大簡化了我們開發的工作量。作為一個插件系統來說,實現一個通用的插件能在更大粒度上進行復用。插件是比控件更加高層的一種模塊封裝方式。

            插件和控件有相同的地方:封裝和復用。本文分析了它們的異同,并且提出另外一個比較有趣的概念——偽插件。請大家繼續往下讀一讀。

            一、插件和控件的比較

            發布

            控件編譯到系統中,和系統作為一個整體發布。

            插件是在系統的運行過程中動態關聯到系統上,可以和系統的其他部分保持物理上的隔離。

            配置能力

            控件在系統中的呈現方式在編譯時已經確定,通過代碼描述控件的表現形式,呈現位置等。

            插件的呈現方式在運行的時候根據外部的配置文件指定。

            功用

            控件作為公用的組件使用,在我們編寫業務模塊時,控件作為基本資源被我們使用。

            插件作為一個獨立的業務模塊存在,直接面向用戶。

            開發調試

            控件的調試簡單,但插件的調試卻比較麻煩。正是因為為了靈活性而制造的隔離措施導致了調試上的困難。通常一個插件作為一個工程開發。

            二、插件與控件的關系

            插件是業務模塊,就像上面所說的,在我們編寫業務模塊時控件作為基本資源被使用。所以插件與控件的關系如下圖左所示,普通的業務模塊如下圖右所示。

            clip_image015

            可以看到,插件是滿足一定接口協議的業務模塊。

            三、混亂的界限

            作為控件使用的插件

            如果一個插件中只有一個控件,并且沒有其他的業務邏輯。這種情況下它是插件還是控件?

            clip_image016

            就像上面所說的,插件是帶有一定業務的模塊,并且是直接面向用戶作為一個系統功能來體現的。插件僅僅是封裝了一個控件,并沒有帶有其他的業務。像這種模塊是作為其他插件的子插件使用。如下圖所示。

            clip_image017

            這和我們上面看到的插件內部直接包含控件就不一樣了。控件作為子插件的形式被其他插件使用。

            插件的配置文件中會將自身的屬性作為配置,如標題、圖標、和其他一切可以作為配置的元素。但子插件沒有詳細的配置文件,它的屬性直接通過插件的接口暴露給父插件。

            這類的子插件是介于插件與控件之間的偽插件,因為它并不能獨立地在系統中運行,并且通常情況下不帶有業務邏輯,不能直接給用戶帶來價值。

            發布后可更換控件

            偽插件似乎沒有什么好處,誰會無緣無故地在控件之上再封裝一層作為插件來使用?

            可以想象一下,在系統發布后,我們需要改變某些插件中使用的控件。當然,可以將那些插件全部重新編譯后發布。但如果使用這種偽插件的思路,我們可以開發一個滿足同樣接口的另外一個偽插件,并在內部使用不同的控件實現。這樣就可以在不發布其他插件的情況下,靈活地修改我們使用的控件了。

            額外開銷

            如果所有的控件都像上面的來實現,那簡直是一場惡夢,并且也沒有這個必要。因為這樣做的成本比較大。

            至于實際中是直接用控件,還是用偽插件的技術,那就要看我們的決策了。

             

            posted on 2009-09-02 21:41 肥仔 閱讀(1314) 評論(0)  編輯 收藏 引用 所屬分類: 編程思想

            1000部精品久久久久久久久| 久久99精品久久久大学生| 狠狠综合久久综合88亚洲| 青青青国产成人久久111网站| 久久AV高清无码| 久久久亚洲欧洲日产国码aⅴ| 日本强好片久久久久久AAA| 久久亚洲精品成人无码网站| 久久综合鬼色88久久精品综合自在自线噜噜 | 四虎亚洲国产成人久久精品| 88久久精品无码一区二区毛片| 国产99精品久久| 91久久成人免费| 亚洲精品97久久中文字幕无码| 无码人妻久久一区二区三区蜜桃 | 国产午夜福利精品久久2021| 久久青青草原亚洲av无码app | 精产国品久久一二三产区区别| 亚洲精品午夜国产VA久久成人| 久久亚洲AV成人无码国产| 久久久精品国产sm调教网站 | 91久久婷婷国产综合精品青草 | 久久久久免费精品国产| 久久国产成人精品国产成人亚洲| 香蕉aa三级久久毛片| 欧美午夜精品久久久久免费视| 日本久久久久久中文字幕| 精品久久久无码中文字幕| 囯产极品美女高潮无套久久久| 人妻丰满AV无码久久不卡| 99热热久久这里只有精品68| 18禁黄久久久AAA片| 久久国产乱子精品免费女| 亚洲午夜久久久| 久久精品国产91久久综合麻豆自制| 欧美无乱码久久久免费午夜一区二区三区中文字幕 | 97视频久久久| 国产精品va久久久久久久| 久久婷婷色香五月综合激情| 精品免费tv久久久久久久| 97视频久久久|