日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

IAdaptable和IAdaptableFactory

 jinzq 2007-04-13

1. 簡介和簡單的實現(xiàn)

IAdapteable實際上在Eclipse早期版本中不叫這個名字,它原來的名字叫做IExtensible,顧名思義就是可以擴展的意思,后來為了更能突出是由一個類配適到一個接口這么一種機制,所以改名為IAdaptable。
這個接口有什么用呢,其實說白了,就是提供一個類型的轉(zhuǎn)換機制。比如下面這段代碼:

Class IAdaptable  
public   interface
 IAdaptable  {
 
public
 Object getAdapter(Class clazz);
}

Class ListAdapter
public   class  ListAdapter  extends  ArrayList  implements
 IAdaptable 

{
 
public
 Object getAdapter(Class clazz) {
  
if (clazz  ==  Vector. class
){
   Vector v 
=   new  Vector( this
.size());
   v.addAll(
this
);
   
return
 v;
  }
  
return   null
;
 }
}


ListAdapter 類繼承了ArrayList,并且實現(xiàn)了IAdaptable接口,我們想要將它轉(zhuǎn)化成Vector類型對象,于是在getAdapter方法中我們判斷 傳入?yún)?shù)類型,如果是Vector類那么就新生成一個Vector對象,將ArrayList中的值全部賦給它,并返回。

這樣,我們就可以寫出以下代碼:

ListAdapter list  =   new  ListAdapter();
  Vector v 
=  (Vector) list.getAdapter(Vector. class );


ArrayList會返回Vector對象,這個對象是ArrayList的一個另外一種類型的副本。

2.一個Swing程序

讀者會問:這有什么用啊,不就簡單轉(zhuǎn)化一下麼。其實說實話,從上面的代碼來看確實沒什么用,但是如果我們換一個場景試試。

寫 這么一個Swing程序:有一個對話框,其中它有一個ComboBox和一個Table,ComboBox中存放的是一個名為Person類型的對象,當 ComboBox的選項發(fā)生改變的時候,就在Table上顯示它的屬性,我們假設(shè)這個Swing程序已經(jīng)在某個項目中開始實施,并且其界面布局不易更改。

看看代碼:

Class person
public   class
 Person {
 
private  String name  =   " name "
;
 
private  String age  =   " 23 "
;
 
private  String sex  =   " male "
;
 
 
public
 Person(String name){
  
this
.setName(name);
 }
 
 
public
 String getName() {
  
return
 name;
 }
 
 
public   void
 setName(String name) {
  
this .name  =
 name;
 }
 ……
}

UI類的部分代碼:

{
       table 
=   new
 JTable();
       
this
.getContentPane().add(table);
       table.setBounds(
218 2 171 248
);
      }
      {
       ComboBoxModel jComboBox1Model 
=   new
 DefaultComboBoxModel(
        
new  Object[] {  new  Person( " rEloaD " ),  new  Person( " b "
) });
       comboBox 
=   new
 JComboBox();
       
this
.getContentPane().add(comboBox);
       comboBox.setModel(jComboBox1Model); 
       comboBox.addActionListener(
new
 ActionListener(){
                 
public   void
 actionPerformed(ActionEvent e){
                     JComboBox comboBox 
=
(JComboBox)e.getSource();
                     Person p 
=
 (Person)comboBox.getSelectedItem();
                     TableModel jTable1Model 
=   new
 DefaultTableModel(
                                     
new  String[][] { {  " Name "
, p.getName() },
                                                       { 
" Sex "
, p.getSex() },
                                                      { 
" Age "
, p.getAge() }},
                                     
new  String[] {  " Column 1 " " Column 2 "
 });
                     table.setModel(jTable1Model);
                      }
                  });

      }




 運行我們的代碼,會發(fā)現(xiàn)效果還可以,每當我們選項改變的時候,Table就如同一個屬性欄一樣,改變著自己的內(nèi)容:


3.需求變更

OK,問題來了。我寫完這段代碼后,組長告訴我,現(xiàn)在我們有一個新的需求,就是Combox中不僅僅有Person類型存在,而且還有一些貨物(Product)類型,也就是說,我的table顯示屬性不能光針對Person這個類型了,還需要顯示Product的屬性。

我心里罵了句:早TMD干嘛了,都快交活兒了才告訴我。

無奈,我新增加了一個Product類型,然后更改了ActionListener中的部分代碼:

JComboBox comboBox  = (JComboBox)e.getSource();
 Object obj 
=
 comboBox.getSelectedItem();
 TableModel jTable1Model 
=   null
;
  
if (obj  instanceof
 Person){
      jTable1Model 
=   new
 DefaultTableModel(
                          
new  String[][] { {  " Name "
, ((Person)obj).getName() },
                                           { 
" Sex "
, ((Person)obj).getSex() },
                                            { 
" Age "
, ((Person)obj).getAge() }},
                           
new  String[] {  " Column 1 " " Column 2 "
 });
  }
  
if (obj  instanceof
 Product){
      jTable1Model 
=   new
 DefaultTableModel(
                        
new  String[][] { {  " Name "
, ((Product)obj).name },
                                          { 
" price "
, ((Product)obj).price },
                                          { 
" quantity "
, ((Product)obj).quantity }},
                         
new  String[] {  " Column 1 " " Column 2 "
 });

  }
  table.setModel(jTable1Model);



結(jié)果還是讓人滿意的:


后來我感覺ActionListener代碼有一些凌亂,又封裝了一個Builder類,讓它創(chuàng)建TableModel:

public   static  TableModel modelBuilder(Object obj){
TableModel jTable1Model = null;
  
if (obj  instanceof
 Person){
          jTable1Model 
=   new
 DefaultTableModel(
             
new  String[][] { {  " Name "
, ((Person)obj).getName() },
               { 
" Sex "
, ((Person)obj).getSex() },
               { 
" Age "
, ((Person)obj).getAge() }},
             
new  String[] {  " Column 1 " " Column 2 "
 });
                          }
                          
if (obj  instanceof
 Product){
                            jTable1Model 
=   new
 DefaultTableModel(
               
new  String[][] { {  " Name "
, ((Product)obj).name },
                 { 
" price "
, ((Product)obj).price },
                 { 
" quantity "
, ((Product)obj).quantity }},
               
new  String[] {  " Column 1 " " Column 2 "
 });

  }
return
 jTable1Model;

}


我對自己的代碼還算滿意,至少目前能用了。

4.需求又變了

第二天,組長告訴我,需求又變了,這會不但多增加一個“服裝”類型,Product類型屬性顯示有錯誤,并且需要增加一個Tree,顯示當前同種類型直接的層次結(jié)構(gòu),等等。

我聽了領(lǐng)導嘮叨半個小時后,打開了我剛寫的Builder類,往里面增加著我的代碼……

類圖大致如下:




程序經(jīng)過修改后,好不容易又符合要求了,情況又發(fā)生了變化,組長需要我繼續(xù)修改。我無奈地看著組長,組長也無奈地看著我那用if-else堆成的代碼……

“悲哀,真讓我替你感到悲~哀!”組長操著本山的腔調(diào)這樣對我說。

是啊,多悲哀啊,一個設(shè)計上的錯誤讓我的代碼無法適應(yīng)需求的變化。



好了,讓我們回到IAdaptable上。

通過上面的例子,我看可以發(fā)現(xiàn)這么一個情況:同樣一個對象,在程序里面往往有許多不同的顯示方式(不僅僅是在UI顯示,在其他一些代碼里,需要轉(zhuǎn)化成另外類型或者數(shù)據(jù)結(jié)構(gòu))。

如果我用IAdapteable的思想來實現(xiàn)剛才的Swing屬性顯示,會怎么樣呢?

重新寫一遍ActionListener中的代碼:

JComboBox comboBox  = (JComboBox)e.getSource();
Object obj 
=
 comboBox.getSelectedItem();
TableModel jTable1Model 
=   null
;
if (obj  instanceof
 IAdaptable){
       jTable1Model 
=  (TableModel) ((IAdaptable)obj).getAdapter(TableModel. class
);
}
table.setModel(jTable1Model);

然后分別讓Person和Product實現(xiàn)IAdaptable接口:

Class Person:
public   class  Person  implements
 IAdaptable{
   …..
   
public
 Object getAdapter(Class clazz) {
  
if (clazz  ==  TableModel. class
){
    
return   new
 DefaultTableModel(
      
new  String[][] { {  " Name "
, getName() },
        { 
" Sex "
, getSex() },
        { 
" Age "
, getAge() }},
      
new  String[] {  " Column 1 " " Column 2 "
 });
  }
  
return   null
;
 }
}

Class Product
public   class  Product  implements
 IAdaptable{
 ……
    
public
 Object getAdapter(Class clazz) {
  
if (clazz  ==  TableModel. class
){
    
return   new
 DefaultTableModel(
      
new  String[][] { {  " Name "
, getName() },
        { 
" Sex "
, getSex() },
        { 
" Age "
, getAge() }},
      
new  String[] {  " Column 1 " " Column 2 "
 });
  }
  
return   null
;
 }
}

其實我們的代碼量并沒有任何的改變,前后都是一樣的。

但 是我們將Table需要顯示的模型(TableModel),現(xiàn)在是作為擴展類接口抽取了出來,而那些需要在Table上顯示自己屬性的業(yè)務(wù)模型 (Person,Product)實現(xiàn)了IAdaptable接口,將顯示模型(TableModel)作為了自己的擴展接口類型給予實例返回,并且UI 代碼中,Table和業(yè)務(wù)模型之間形成一種契約:凡是實現(xiàn)了IAdaptable的接口才可以獲得在該Table上顯示的資格,并且Table從 IAdaptable的getAdapter方法獲得顯示模型:



這樣一來,我們的Swing程序不僅功能能夠?qū)崿F(xiàn),而且UI部分代碼和業(yè)務(wù)模型代碼之間的耦合性減小了。

而 且,如果需求發(fā)生變化,比如像剛才提到那樣“需要增加一個Tree,顯示當前同種類型直接的層次結(jié)構(gòu)”,那我們就在getAdaper方法中返回一個 TreeModel的副本,然后在UI中增加一個Tree,讓它像Table一樣,從IAdaptable接口中取出我們的TreeModel即可—— UI擴展也變得容易起來。

現(xiàn)在我可以對組長說:讓需求變化來得更猛烈些吧!


5.模型代碼無法修改

有這樣一個問題:如果我們的模型已經(jīng)存在,而且代碼已經(jīng)無法修改了怎么辦?

IAdapterFactory就是為這種情況準備的。

先看看IAdapterFactory:

public   interface  IAdaptableFactory {
 
public
 Object getAdapter(Object adapter,Class clazz);
}


這里面的方法和IAdaptable差不多,只是多了一個參數(shù),這個參數(shù)就是需要我們返回Adapter接口的對象。

在Eclipse中IAdapterFactory并不是單獨存在的,而是有一個IAdapterManager對它進行維護的:

public   interface  IAdaptableManager {
 
public
 Object getAdapter(Object adapter,Class clazz);
 
public   boolean
 registerAdapters (Class clazz,IAdaptableFactory factory);
}


現(xiàn)在讓我們這樣來修改剛才的Swing程序:

假設(shè)Product類型是第三方提供的jar包,我們已經(jīng)無法修改它的代碼了,那我們就需要用到IAdapableFactory的擴展方法。請看下面的代碼

Class AdaptableFactoryImpl
public   class  AdaptableFactoryImpl  implements
 IAdaptableFactory {
 
public
 Object getAdapter(Object adapter, Class clazz) {
  
if (adapter  instanceof
 Product){
   
if (clazz  == TableModel. class
){
    
return   new
 DefaultTableModel(
      
new  String[][] { {  " Name "
,((Product)adapter).name },
        { 
" price "
, ((Product)adapter).price },
        { 
" quantity "
, ((Product)adapter).quantity }},
      
new  String[] {  " Column 1 " " Column 2 "
 });
   }
  }
  
return   null
;
 }
 
public
 Class[] getAdapterList() {
  
return   new  Class[]{TableModel. class
};
 }
}

Class AdapterManagerImpl:
public   class  AdapterManagerImpl  implements
 IAdaptableManager {
 
private   static  AdapterManagerImpl instance  =   null
;
 
private  Hashtable table  =   new
 Hashtable();
 
 
private
 AdapterManagerImpl(){}
 
 
public
 Object getAdapter(Object adapter, Class clazz) {
  Object factory 
=
 table.get(adapter.getClass());
  
if (factory  !=   null
){
   
return
 ((IAdaptableFactory)factory).getAdapter(adapter,clazz);
  }
  
return   null
;
 }

 
public   boolean
 registerFacotry(Class clazz, IAdaptableFactory factory) {
  
try
{
   table.put(clazz,factory);
   
return   true
;
  }
catch
(Exception e){
   
return   false
;
  }
 }
 
public   synchronized   static
 AdapterManagerImpl getInstance() {
  
if (instance  ==   null ) instance  =   new
 AdapterManagerImpl();
  
return
 instance;
 }
}


有了這兩個實現(xiàn)類后,我們再去修改一下ActionListener中的代碼:

         JComboBox comboBox  =  (JComboBox) e.getSource();
         Object obj 
=
 comboBox.getSelectedItem();
         TableModel jTable1Model 
=   null
;
         
if  (obj  instanceof
 IAdaptable) {
          jTable1Model 
=
 (TableModel) ((IAdaptable) obj)
            .getAdapter(TableModel.
class
);
         } 
else
 {
          jTable1Model 
=
 (TableModel) AdapterManagerImpl
            .getInstance().getAdapter(obj,
              TableModel.
class
);
         }
         table.setModel(jTable1Model);


好了,只要我們在適當?shù)牡胤?,將IAdaptableFactory注冊進IAdaptaerManager,那我們對無法修改代碼的業(yè)務(wù)模型也能進行接口的擴展了。

6.結(jié)束語

在Eclipse中,IAdaptable的應(yīng)用非常廣泛,而且如果實現(xiàn)了IAdaptable接口的類被成為Platform Object,可見IAdaptable在Eclipse框架中的分量。本人的知識有限,如果有遺漏或者錯誤的地方,還請各位讀者指出。

轉(zhuǎn)貼網(wǎng)址:http://www./reloadcn/archive/2006/10/09/iadaptable.html

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多