Live a simple life

          沉默(zhu_xing@live.cn)
          隨筆 - 48, 文章 - 0, 評(píng)論 - 132, 引用 - 0
          數(shù)據(jù)加載中……

          【Eclipse插件開發(fā)】Eclipse中類型擴(kuò)展機(jī)制分析

           

                                  Eclipse中類型擴(kuò)展機(jī)制分析

                                                                                                            朱興(zhu_xing@live.cn

          概要

                 在本篇文章中,將討論如下關(guān)鍵內(nèi)容:

          1、 標(biāo)準(zhǔn)的適配器模式,包括類適配器模式和對(duì)象適配器模式,及其各自的優(yōu)缺點(diǎn)

          2、 Eclipse runtime中的類型擴(kuò)展機(jī)制,包括擴(kuò)展類型的自動(dòng)回調(diào)機(jī)制、已知擴(kuò)展類型支持和未知擴(kuò)展類型支持的討論

          3、 插件開發(fā)過程中,合理的使用Eclipse runtime中的類型擴(kuò)展機(jī)制需要注意的地方

          說明:假設(shè)讀者大致了解適配器模式,對(duì)設(shè)計(jì)模式的使用有一點(diǎn)經(jīng)驗(yàn)

          標(biāo)準(zhǔn)適配器模式

                 適配器模式應(yīng)該是我們?nèi)粘K褂米疃嗟慕Y(jié)構(gòu)型模式之一,“適配器模式把一個(gè)類的接口變換為客戶端所期望的另一種接口,從而使原本因接口不匹配而無法在一起工作的兩個(gè)類能夠在一起工作”。

                 適配器模式的實(shí)現(xiàn)有兩種方式,借用《Java與模式》一書中的描述,將其稱之為類適配器模式和對(duì)象適配器模式,這兩種適配器模式也為我們很好地演繹了繼承和組合這兩種主要的代碼復(fù)用方式。與此同時(shí),繼承和組合這兩種代碼的復(fù)用方式有其各自的適用場(chǎng)景(還是那句話,需求決定我們?cè)撛趺锤?/span> _~),而兩種適配器模式不恰當(dāng)使用本質(zhì)上也是和兩種代碼復(fù)用方式的不恰當(dāng)使用緊密相關(guān)的。

                 為了便于下面的討論,我們延用設(shè)計(jì)模式書籍中使用的三個(gè)角色:

                 Adaptee(源,待適配):需要適配的類型,行為需要被復(fù)用

                 Target(目標(biāo)):適配的方向,也就是我們期待的接口,客戶端定義的契約

                 Adapter(適配器):承擔(dān)類型匹配任務(wù)的具體類,Target類型實(shí)現(xiàn)類

                 說明:Adapter是需要實(shí)例化使用的,所以是具體類,而Target代表目標(biāo)類型的抽象

                 下面,我們就簡(jiǎn)要看一下類適配器模式和對(duì)象適配器模式。具體細(xì)節(jié),可以參加《Java與模式》一書(當(dāng)然,GOF的《設(shè)計(jì)模式》也可以 _~)

          類適配器模式

                  

                 我們的適配器Adapter同時(shí)繼承了目標(biāo)類型Target(當(dāng)然,這是必須的)和源Adaptee

                 缺點(diǎn):

          1.如果源Adaptee有一系列類型(有共同的頂級(jí)父類型),那我們需要對(duì)這一系列類型

          中的每個(gè)類型(源及其子類型)都產(chǎn)生一個(gè)適配器類實(shí)現(xiàn),也就是說,會(huì)引入大量的類型,帶來類型膨脹的問題。

          2.如果Target是一個(gè)抽象類,那么這樣做在不支持多繼承的編程語言(例如javac#)中是行不通的。(注意,既有代碼很有可能是以抽象類來扮演Target類型體系的頂級(jí)類型,畢竟很多開發(fā)者并不能非常清晰的來判斷如何區(qū)別使用接口和抽象類)。

          優(yōu)點(diǎn):

          由于是繼承了源,所以可以定制源類型的默認(rèn)行為。注意,第一只能定制源類型體系中的某一特定類型,第二,這帶來了實(shí)現(xiàn)細(xì)節(jié)的耦合,而且定制有可能帶來用戶的疑惑,因?yàn)樘囟ㄔ搭愋偷哪J(rèn)行為被修改了。

          對(duì)象適配器模式

          我們的適配器Adapter繼承了目標(biāo)類型Target(當(dāng)然,這是必須的),組合了源Adaptee

          缺點(diǎn):

          無法定制Adaptee的行為。(其實(shí)也可以定制,需要引入另外的一個(gè)特殊的中間類型)

          優(yōu)點(diǎn):

          1. 由于采用了組合的方式,所以可以一次性的將引用的源類型及其子類型都適配到目標(biāo)接口。這避免了從一種類型體系適配到另一種類型體系的過程中,產(chǎn)生大量的類型,避免了類型膨脹的問題(這也是Eclipse想極力避免的)。

          2. 最根本的優(yōu)勢(shì)是,適合我們開發(fā)過程所面對(duì)的絕大多數(shù)適配需求。因?yàn)樵谠O(shè)計(jì)良好的OO系統(tǒng)中,適配需求往往是將一個(gè)類型體系適配到另外一個(gè)類型適配體系,而每個(gè)類型體系往往都遵循了開閉原則,只暴露了抽象部分給客戶端(橋模式能夠很好的分離抽象和實(shí)現(xiàn)并使其獨(dú)立變化)。

          示例演示和進(jìn)一步討論

          下面我們接著討論一下,類型體系適配需求示意如下:

          (說明:上圖中的紅色部分,就是我們所說的內(nèi)部實(shí)現(xiàn),不希望對(duì)用戶可見)

                        【客戶端模擬需求】

                          

           1 publicclass Customer {
           2 
           3            /**
           4 
           5             *模擬使用場(chǎng)景
           6 
           7             *
           8 
           9             *@paraminstanceInterface2類型的實(shí)例
          10 
          11             */
          12 
          13            publicstaticvoid run(Interface2 instance) {
          14 
          15               instance.operation();
          16 
          17            }
          18 
          19 }
          20 

           

          Interface2類型對(duì)象適配器】

           1 publicclass Interface2Adapter implements Interface2{
           2 
           3            private Interface1 interface1Instance;
           4 
           5     
           6 
           7            public Interface2Adapter(Interface1 instance) {
           8 
           9               this.interface1Instance = instance;
          10 
          11            }
          12 
          13     
          14 
          15            /* (non-Javadoc)
          16 
          17             * @see Interface2#operation()
          18 
          19            */
          20 
          21            publicvoid operation() {
          22 
          23               this.interface1Instance.operation();
          24 
          25            }
          26 
          27 }
          28 
          29 


          適配器使用

              

           1 public class Test {
           2 
           3     public static void main(String[] args) {
           4        Interface2 instance1 = new Interface2Adapter(new Interface1Impl());
           5        Customer.run(instance1);
           6 
           7 
           8        Interface2 instance2 = new Interface2Adapter(new Interface1Imp2());
           9        Customer.run(instance2);
          10     }
          11 }
          12 

          我們可以看到,我們的Interface2Adapter構(gòu)造函數(shù)接收的是一個(gè)Interface1抽象類型,理論上我們可以用這一個(gè)Adapter類完成Interface1類型體系到Interface2類型體系的適配。

          疑問和進(jìn)一步討論?

          1、我們的適配能夠被自動(dòng)識(shí)別并使用嗎?

          分析一下上面的實(shí)例演示我們發(fā)現(xiàn),在Java語言中并沒有相應(yīng)的機(jī)制來判斷一個(gè)類型是否是可以適配的:上面的客戶端Customer需要的目標(biāo)類型是Interface2類型,如果直接給它一個(gè)Interface1類型,Customer并不能判斷出來Interface1是否本身是可以被適配到其他類型。

          既然Java語言機(jī)制中沒有默認(rèn)提供一種判斷特定類型是否可以適配到其他類型的機(jī)制,那么考慮到用戶的使用,一些類型在作為API暴露的同時(shí),也需要將其對(duì)應(yīng)的適配器作為API的一部分進(jìn)行暴露。例如,上面例子中的Interface1作為API暴露,如果不暴露對(duì)應(yīng)的適配器Interface2Adapter(作為內(nèi)部實(shí)現(xiàn)隱藏)那么Interface1的用戶在面對(duì)Customer(接受的目標(biāo)類型是Interface2)需求的時(shí)候遇到麻煩,他們不知道Interface1可以適配到Interface2,他們就可能需要自行開發(fā)對(duì)應(yīng)的適配器。所以,我們開發(fā)一般的Java應(yīng)用的時(shí)候,也確實(shí)是這么做的,將需要暴露的類型和默認(rèn)提供的一些適配器也一起暴露。但是如果進(jìn)一步想一下,如果類型的適配需求特別廣泛(注明:很多場(chǎng)景可能需要特定類型提供額外的服務(wù),而這些服務(wù)并不能算是這種類型需要提供的核心服務(wù)),那么可能就需要提供并暴露大量的適配器類型給用戶(這當(dāng)然是有點(diǎn)不優(yōu)雅的)。

          有什么更好的辦法嗎?聯(lián)想一下,在Java語言中提供了一些類似的解決辦法可以供參考,例如java.long.Cloneable接口就聲明了一種類型可以被克隆的等等。那么如果我們也定義類似的接口,就叫做IAdaptable,來聲明一種類型可以被適配,再在接口中提供一個(gè)操作getAdapter來獲取對(duì)應(yīng)的適配器實(shí)例,這樣的話我們就可以將我們的適配器類型進(jìn)行隱藏。這樣,只需要將類型的核心服務(wù)暴露給用戶,如果用戶想請(qǐng)求額外的服務(wù),可以調(diào)用getAdapter來獲取對(duì)應(yīng)的目標(biāo)類型(當(dāng)然,我們?cè)陬愋偷?/span>API文檔中告訴用戶我們的類型可以默認(rèn)被是適配為那些類型)。按照這個(gè)思路我們的代碼修改如下:

                               //聲明類型具有可以被適配為其他類型的能力

          publicinterface IAdaptable {

                         public Object getAdapter(Class adapter);

          }

          //修改我們的Interface1類型接口定義,聲明其可以被適配為別的類型

          publicinterface Interface1 extends IAdaptable{

                         publicvoid operation();

          }

          //修改我們的Interface1的類型實(shí)現(xiàn),實(shí)現(xiàn)IAdaptable.getAdapter邏輯
              

           1 publicclass Interface1Impl implements Interface1{
           2 
           3      public void operation() {
           4           //todo:
           5      }
           6 
           7      public Object getAdapter(Class adapter) {
           8          //實(shí)現(xiàn)適配邏輯,適配到Interface2類型
           9           if (Interface2.class == adapter)
          10             return new Interface2Adapter(this);
          11             return null;
          12      }
          13 }
          14 
          15 

           

                 //修改我們的客戶端代碼
                      

           1 public class Customer {
           2      public static void run(Object source) {
           3         //首先檢查本身是否為Interface2類型
           4          if (source instanceof Interface2)
           5            ((Interface2) source).operation();
           6 
           7         //檢查類型是否可以被適配,如果可以,嘗試往Interface2類型適配
           8           else if (source instanceof IAdaptable) {
           9             IAdaptable adaptable = ((IAdaptable)source);
          10             Object instance = adaptable.getAdapter(Interface2.class);
          11             if (instance != null)
          12                ((Interface2) instance).operation();
          13         }
          14     }
          15 }
          16 


          說明:現(xiàn)在我們的客戶端接受的是一個(gè)弱類型了(其實(shí)應(yīng)該是半弱類型,有相應(yīng)的類型檢查)

          2、在能夠被自動(dòng)識(shí)別和使用的基礎(chǔ)上,能否允許用戶參與提供適配的過程?

          //接著修改我們的Interface1Impl實(shí)現(xiàn)

           

           1 public class Interface1Impl implements Interface1{
           2      public void operation() {
           3          //todo:
           4      }
           5 
           6      public Object getAdapter(Class adapter) {
           7          //自定義適配邏輯(已知擴(kuò)展),適配到Interface2類型
           8           if (Interface2.class == adapter)
           9             return new Interface2Adapter(this);
          10 
          11          //TODO: 調(diào)用別人貢獻(xiàn)的適配邏輯
          12           return AdapterManager.getAdapter(this, adapter)
          13      }
          14 }
          15 

           

          上面的代碼僅僅是示意性的代碼,AdapterManager類型也是暫時(shí)杜撰出來的。我們可以假設(shè)目前AdapterManager的作用是管理別人貢獻(xiàn)的適配邏輯,用只需要將對(duì)應(yīng)的適配邏輯注冊(cè)到AdapterManager中,就可以參與到Interface1Impl的適配邏輯中,太完美了~_~。

          Eclipse中的類型擴(kuò)展機(jī)制

                 Eclipse平臺(tái)本身是一個(gè)微內(nèi)核(micro kernel)加核心插件(core plug-ins)的結(jié)構(gòu),微內(nèi)核是指EcllipseOSGI實(shí)現(xiàn)Equinox(當(dāng)然包含了擴(kuò)展點(diǎn)機(jī)制的支持),這里的核心插件就是指:runtimeresourceworkbench。而這里的平臺(tái)運(yùn)行時(shí)為我們提供的主要的特性是:類型擴(kuò)展支持(IAdaptableIAdapterFactoryIAdapterManager)和線程支持(JobISchedulingRule)。我們今天要討論的就是類型擴(kuò)展支持。

          Eclipse中的類型擴(kuò)展需求

                 Eclipse中,一個(gè)特性類型經(jīng)常會(huì)收到這樣的請(qǐng)求:請(qǐng)?zhí)峁╊~外的服務(wù)。例如,用戶在一個(gè)視圖(提供了workbench seleciton service服務(wù),)中選中了一個(gè)元素,這時(shí)候視圖會(huì)發(fā)送選擇事件出去,告訴其他視圖用戶選中了一個(gè)元素,屬性視圖(Properties View)接受到了這個(gè)選擇事件,就會(huì)向選中的對(duì)象發(fā)送請(qǐng)求:請(qǐng)?zhí)峁┠軌蛟趯傩砸晥D顯示的服務(wù)。請(qǐng)注意,這種場(chǎng)景在Eclipse太普遍不過了,根源于Eclipse定位為一個(gè)可擴(kuò)展的平臺(tái),便于擴(kuò)展和集成是Eclipse開發(fā)者的最大需求之一!!!

                 我們接著分析一下這種額外的服務(wù)。假設(shè)目前我們?cè)诙x一種類型,我們可能會(huì)將類型提供的服務(wù)劃分為兩類,以org.eclipse.core.resources.IResource為例:

                 核心服務(wù):提供對(duì)底層資源的句柄代理(提供movedeletecopygetFullPath等操作),直接以API的方式暴露給用戶。

                 額外服務(wù):需要類型擴(kuò)展。進(jìn)一步將額外服務(wù)劃分為兩類:已知額外服務(wù)(類型定義時(shí)提供)和未知額外服務(wù)(類型發(fā)布之后,用戶參與貢獻(xiàn)的額外服務(wù))。對(duì)應(yīng)的擴(kuò)展類型我們將其稱之為已知擴(kuò)展類型和未知擴(kuò)展類型。對(duì)IResource類型來說,由于資源管理是Eclipse底層的核心模塊,在這個(gè)層面上面,它不可能為上層的功能模塊提供類型擴(kuò)展,因?yàn)檫@違反了模塊分層劃分的原則。但是,IResource作為一個(gè)底層類型,肯定是要求可以擴(kuò)展的,所以Eclipse針對(duì)IResource類型采用了邀請(qǐng)外部擴(kuò)展(允許外部提供未知類型的適配器)的方式,詳細(xì)信息會(huì)在下面分析。

          Eclipse中的類型擴(kuò)展機(jī)制

                 Eclipse類型擴(kuò)展機(jī)制的核心本質(zhì)】

                 Eclipse中的類型擴(kuò)展機(jī)制,核心內(nèi)容就是補(bǔ)充了Java語言的缺陷提供了自定義的類型擴(kuò)展機(jī)制,基本上就是回答了上面的兩個(gè)問題:

                 1我們的適配能夠被自動(dòng)識(shí)別并使用嗎?

                        Eclipse提供了org.eclipse.core.runtime.IAdaptable,用來聲明特定類型是否是可以

                 被適配的(adaptable)。并提供了默認(rèn)適配器類org.eclipse.core.runtime.PlatformObject

                 Eclipse中,只要是繼承自以上接口或者抽象類的類型,就被視為“可擴(kuò)展類型”。

              2在能夠被自動(dòng)識(shí)別和使用的基礎(chǔ)上,能否允許用戶參與提供適配的過程?

                        Eclipse為我們提供了IAdapterFactoryorg.eclipse.core.runtime.IAdapterFactory

                 IAdapterManagerorg.eclipse.core.runtime.IAdapterManager)。用可以將自定義的

                 適配邏輯放入IadapterFactory中,然后注冊(cè)到IadapterManager中,注冊(cè)方式如下:

          1、 通過代碼靜態(tài)注冊(cè)(一般選擇在插件啟動(dòng)時(shí))

          IAdapterFactory.registerAdapters(IAdapterFactory factory, Class adaptable);

          2、 通過擴(kuò)展點(diǎn)方式動(dòng)態(tài)掛入

          org.eclipse.core.runtime.adapters擴(kuò)展點(diǎn)(詳細(xì)信息參加Eclipse help

                 【已知類型擴(kuò)展和未知類型擴(kuò)展】

                 再接下來的討論之前,我們先來區(qū)分兩個(gè)概念(這兩個(gè)概念是俺大致起的,湊合著看吧~_~)。我們修改一下Interface1Impl實(shí)現(xiàn)如下:

                

          1 public abstract class PlatformObject implements IAdaptable {
          2     public Object getAdapter(Class adapter) {
          3         return AdapterManager.getDefault().getAdapter(this, adapter);
          4     }
          5 
          6 }
          7 

           

                

           1 public class Interface1Impl extends PlatformObject{
           2     public void operation() {
           3         //todo:
           4     }
           5 
           6       /* 
           7        * 已知擴(kuò)展類型:Interface2
           8        * 未知擴(kuò)展類型:遵循Eclipse”邀請(qǐng)法則“,兼容未知擴(kuò)展類型
           9         * @see PlatformObject#getAdapter(java.lang.Class)
          10        */
          11 
          12      public Object getAdapter(Class adapter) {
          13          //已知擴(kuò)展類型,適配到Interface2類型
          14            if (Interface2.class == adapter)
          15                return new Interface2Adapter(this);
          16 
          17          // 兼容未知擴(kuò)展類型,通過PlatformObject.getAdapter查詢
          18            return super.getAdapter(adapter);
          19     }
          20 }
          21 
          22 


              已知擴(kuò)展類型:類型定義者默認(rèn)提供了對(duì)應(yīng)的適配器實(shí)現(xiàn),例如Interface2適配的Interface2Adapter未知擴(kuò)展類型:以IAdapterFactory方式提供的類型統(tǒng)稱為未知擴(kuò)展類型,通過IAdapterManager#getAdapter方法查詢使用。可能有人會(huì)問,我在定義一個(gè)類型的時(shí)候,就把類型適配邏輯放入到一個(gè)adapter factory中注冊(cè)到了IAdapterManager這應(yīng)該算是已知擴(kuò)展類型啊?但是對(duì)于Eclipse來說,其默認(rèn)會(huì)遵守公平法則,即一個(gè)IAdapterFactory無論是那個(gè)開發(fā)者提供的,它并不關(guān)心,都是平等的。

          使用Eclipse中的類型擴(kuò)展機(jī)制注意點(diǎn)

          【已知類型擴(kuò)展和未知類型擴(kuò)展】

                 已知擴(kuò)展類型對(duì)于我們來說是很有把握的,既考慮到了靈活性又兼顧到了穩(wěn)定性。而對(duì)于未知擴(kuò)展類型來說,雖然有很大的靈活性,但是也帶來了不穩(wěn)定性,畢竟這個(gè)適配類型不是自己提供的。這邊就需要有兩個(gè)事情需要考慮:

          1、 是否需要提供對(duì)未知擴(kuò)展類型的支持

          Eclipse底層定義的很多類型都提供了對(duì)未知擴(kuò)展類型的兼容,咱們自己定義的類型倒不一定。如果你能確定自定義的類型沒有類型擴(kuò)展的需求,那么就不要繼承IAdaptable接口或者PlatformObject類。如果你能確定自定義的類型有非常明確的類型擴(kuò)展需求,并且能確定需要適配到那幾種類型,那就只提供已知類型擴(kuò)展。在確定自定義的類型有廣泛的類型擴(kuò)展需求的情況下,再兼容未知擴(kuò)展類型,這種類型一般來說是處于你應(yīng)用中的底層模塊中。

          2、 明確已知擴(kuò)展類型和未知擴(kuò)展類型之間的優(yōu)先級(jí)

          建議是將已知擴(kuò)展類型設(shè)為高優(yōu)先級(jí),對(duì)IAdapterManager#getAdapter查詢得到的未知擴(kuò)展類型設(shè)為低優(yōu)先級(jí)別。注意,外部提供的未知擴(kuò)展類型之際是不存在顯示的優(yōu)先級(jí)別的,IAdapterManager#getAdapter會(huì)對(duì)注冊(cè)的IAdapterFacotry進(jìn)行深度優(yōu)先查找,查詢到第一個(gè)合適的就直接返回。

           

          【如何提供類型擴(kuò)展】

          1、 不能破壞模塊分層原則,基礎(chǔ)模塊不應(yīng)該為上層功能模塊的類型提供適配服務(wù)

          上層功能模塊是建立在基礎(chǔ)模塊的基礎(chǔ)之上的,如果讓基礎(chǔ)模塊為上層功能模塊中的類型提供適配服務(wù),那肯定會(huì)破壞模塊分層的原則,也就沒有所謂的基礎(chǔ)模塊和上層功能模塊的概念了。

          如果基礎(chǔ)模塊中的類型需要適配到特定上層模塊中的類型,也應(yīng)該是該上層模塊自己以IAdapterFactory的方式注冊(cè),上層模塊自己創(chuàng)建對(duì)應(yīng)的IAdapterFactoryAdapter實(shí)現(xiàn)。(當(dāng)然,這就需要待適配的基礎(chǔ)類型本身兼容外部貢獻(xiàn)的未知擴(kuò)展類型,PlatformObject的默認(rèn)實(shí)現(xiàn)就是兼容外部貢獻(xiàn)的未知擴(kuò)展類型的)。

          如果上層模塊中的類型需要適配到底層模塊中的類型,那就在上層模塊中提供適配邏輯,這是很自然的事情。Eclipse的開發(fā)者法則中就有一條:IResource適配法則,鼓勵(lì)開發(fā)者提供自定義類型到IResource系列類型的是適配邏輯。但是,同樣要避免一點(diǎn):非UI模塊不應(yīng)該為UI類型提供適配,否則會(huì)導(dǎo)致核心功能和UI的緊耦合。

          如果是平行層面的模塊呢?例如兩個(gè)上層功能模塊之間可能需要進(jìn)行類型適配,這個(gè)問題就是仁者見仁、智者見智了。個(gè)人的建議是,不要輕易的做這種適配,應(yīng)該首先考慮一下是否可以通過底層模塊作為橋梁,例如首先將模塊A中的類型適配為底層模塊中的類型,然后再將底層模塊中的類型適配為上層模塊B中的類型。如果還行不通,那就請(qǐng)反思一下現(xiàn)有模塊的設(shè)計(jì)劃分是否有問題,例如這兩個(gè)上層功能模塊是否劃分的過細(xì)。如果還行不通,那怎么做就

          看到過有些插件應(yīng)用,里面也有幾十個(gè)插件工程。按照需求分析一下,肯定是有基礎(chǔ)模塊和上層功能模塊的概念,但是實(shí)際的代碼中去基本上反應(yīng)不出來,可能對(duì)于很多人來說,管他基礎(chǔ)模塊還是上層模塊呢,代碼能運(yùn)行就OK了。如果您現(xiàn)在的插件應(yīng)用已經(jīng)做了較好的底層模塊和上層功能規(guī)模的劃分,千萬不要因?yàn)檎`用了Eclipse類型擴(kuò)展機(jī)制而導(dǎo)致破壞了分層,那就非常得不償失了。~_

          2、 不能破壞Eclipse分層原則,非UI插件中定義的類型不應(yīng)該提供UI類型適配服務(wù)

          一定要遵守,否則會(huì)直接破壞Eclipse倡導(dǎo)的分層原則,否則會(huì)造成核心功能和UI的緊密耦合,示意圖如下:

                  

               如上圖所示:

          1、      如果上層模塊A中的非UI類型需要適配到底層模塊core中的非UI類型,請(qǐng)?jiān)?/span>A.core插件中提供適配邏輯

          2、      如果上層模塊A中的非UI類型需要適配為底層模塊UI中的UI類型,請(qǐng)?jiān)?/span>A.UI插件中提供適配邏輯(避免非UIUI耦合)

          3、      如果底層模塊Core中的非UI類型需要適配到上層模塊A.UI中的UI類型,請(qǐng)?jiān)?/span>A.UI插件中提供適配邏輯

          4、      如果,請(qǐng)注意一般UI類型到UI類型的適配基本上情況很少

          Eclipse類型擴(kuò)展機(jī)制的幾個(gè)缺陷】

          未知類型的沖突問題:前面我們分析過,對(duì)多個(gè)未知擴(kuò)展類型之間不存在明顯的優(yōu)先級(jí)別,IAdapterManager#getAdapter會(huì)對(duì)注冊(cè)的IAdapterFacotry進(jìn)行深度優(yōu)先查找,查詢到第一個(gè)合適的就直接返回。如果想獲取高的優(yōu)先級(jí),評(píng)估一下是否可以做為已知擴(kuò)展類型提供,或者直接由定義該類型的插件直接提供IAdapterFactory注冊(cè)。關(guān)于優(yōu)先級(jí)的問題,一般也沒有什么特別好的解決辦法。如果Eclipse提供了優(yōu)先級(jí)的處理,那么可能既增加了用戶使用的復(fù)雜度,同時(shí)也并不能解決沖突的問題。

          IAdapterFactory的有效性問題IadapterManager提供了兩種getAdapterloadAdapter兩種接口如果以org.eclipse.core.runtime.adapters擴(kuò)展點(diǎn)的方式掛入了IAdapterFactory實(shí)現(xiàn)getAdapter的方式不會(huì)去強(qiáng)制啟動(dòng)你的插件,而loadAdapter的方式會(huì)去強(qiáng)制啟動(dòng)你的插件如果是以代碼的方式注冊(cè)的,那也直接取決于所在插件是否啟動(dòng)(你的IAdapterFactory注冊(cè)代碼是否被執(zhí)行了)。這一點(diǎn),很多時(shí)候會(huì)給人造成很大的疑惑

          【如何降低Eclipse類型擴(kuò)展機(jī)制所帶來的編程復(fù)雜度】

                 Eclipse平臺(tái)運(yùn)行時(shí)的類型擴(kuò)展機(jī)制為開發(fā)者帶來了很大的靈活性,但是同時(shí)肯定也帶來編程復(fù)雜度,尤其是對(duì)于經(jīng)驗(yàn)很少的Eclipse插件開發(fā)人員。個(gè)人經(jīng)驗(yàn),那就是如果你的類型實(shí)現(xiàn)了IAdaptable,請(qǐng)?jiān)?/span>API文檔中說明,提供內(nèi)容如下:

          1、 提供了那些已知擴(kuò)展類型。

          2、 是否邀請(qǐng)外部用戶貢獻(xiàn)適配邏輯。

          例如org.eclipse.core.resources.IResource接口的API文檔中有如下信息:

          Resources implement the <code>IAdaptable</code> interface;

          extensions are managed by the platform's adapter manager.

          總結(jié)

                 寫這篇文章的最大目的是希望解釋兩個(gè)事情:

                        Eclipse的類型擴(kuò)展機(jī)制是怎么來的

                        使用Eclipse的類型擴(kuò)展機(jī)制應(yīng)該注意什么

             希望對(duì)大家有所幫助!



          本博客中的所有文章、隨筆除了標(biāo)題中含有引用或者轉(zhuǎn)載字樣的,其他均為原創(chuàng)。轉(zhuǎn)載請(qǐng)注明出處,謝謝!

          posted on 2008-08-18 18:22 zhuxing 閱讀(3998) 評(píng)論(2)  編輯  收藏 所屬分類: Eclipse Plug-in & OSGI

          評(píng)論

          # re: 【Eclipse插件開發(fā)】Eclipse中類型擴(kuò)展機(jī)制分析  回復(fù)  更多評(píng)論   

          寫的非常好,謝謝分享
          2009-10-13 18:03 | heng

          # re: 【Eclipse插件開發(fā)】Eclipse中類型擴(kuò)展機(jī)制分析  回復(fù)  更多評(píng)論   

          深入淺出
          2009-11-26 10:07 | Icarus
          主站蜘蛛池模板: 城口县| 海淀区| 庆城县| 弥勒县| 津市市| 舒城县| 搜索| 新昌县| 吉安县| 宁远县| 博乐市| 光山县| 来凤县| 乡城县| 基隆市| 台东市| 图片| 同仁县| 临漳县| 始兴县| 含山县| 龙口市| 兴和县| 汉中市| 东阿县| 新晃| 涪陵区| 海伦市| 醴陵市| 霍林郭勒市| 东阿县| 叶城县| 勃利县| 和硕县| 怀柔区| 沾化县| 宜良县| 旬邑县| 于田县| 高邑县| 竹北市|