2013-06-26 70 views
2

我有一個第三方RPC-API,它提供了與java.sql.ResultSet(用於讀取值)和java.sql.PreparedStatement(用於寫入值)類似的接口。假設它看起來是這樣的:如何爲ResultSet類API實現泛型包裝?

public interface RemoteDeviceProxy { 
    public void setBoolean(Boolean value); 
    public void setInteger(Integer value); 
    // ... 

    public Boolean getBoolean(); 
    public Integer getInteger(); 
    // ... 
} 

我想寫這個API使用泛型創建特定類型的實例的包裝:我怎樣才能實現我的通用包裝,吸氣

public class <T> RemoteVariable { 
    private final RemoteDeviceProxy wrappedDevice; 

    public RemoteVariable(RemoteDeviceProxy wrappedDevice) { 
     this.wrappedDevice = wrappedDevice; 
    } 

    public T get() { 
     // should call wrappedDevice.getBoolean() if T is Boolean, etc. 
     // how to implement? 
    } 

    public void set(T newValue) { 
     // should call wrappedDevice.setBoolean(newValue) if T is Boolean, etc. 
     // implement using instanceof 
    } 
} 

?我發現this answer其中深入解釋了類似的情況,但我無法將其轉移到我的問題。具體而言,當我寫這篇文章:

public T get() { 
     Type[] actualTypeArguments = ((ParameterizedType) getClass()) 
             .getActualTypeArguments(); 
    } 

我得到一個編譯錯誤說我不能轉換爲ParameterizedType,我不明白爲什麼。任何人都可以解釋如何做到這一點?

回答

2

這裏有一種方法:

public class <T> RemoteVariable { 
    private final RemoteDeviceProxy wrappedDevice; 
    private final Class<T> clazz; 

    public RemoteVariable(RemoteDeviceProxy wrappedDevice, Class<T> clazz) { 
     this.wrappedDevice = wrappedDevice; 
     this.clazz = clazz; 
    } 

    public T get() { 
     if(clazz == Boolean.class){return clazz.cast(wrappedDevice.getBoolean());} 
     else if(clazz == Integer.class){return clazz.cast(wrappedDevice.getInteger());} 
     // ... 
    } 

    // ... 
} 
+0

我沒有想到這一點。由於'RemoteVariable'的實例無論如何都是從工廠創建的,所以這在客戶代碼中並不難看。謝謝! –

2

我認爲在這個很長一段時間,終於想出了一個不同的方法:

首先我添加一個getter你RemoteVariable類:

protected RemoteDeviceProxy getWrappedProxy() { 
    return wrappedProxy; 
} 

第二我創建了一個工廠以後使用的生成器接口:

public interface RemoteVariableBuilder { 
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy); 
} 

然後,我創建的非通用子類Boolean ...

public class RemoteBooleanVariable extends RemoteVariable<Boolean> implements RemoteVariableBuilder { 

    public RemoteBooleanVariable(RemoteDeviceProxy wrappedProxy) { 
     super(wrappedProxy); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) { 
     return (RemoteVariable<T>) new RemoteBooleanVariable(wrappedProxy); 
    } 

    @Override 
    public Boolean get() { 
     return getWrappedProxy().getBoolean(); 
    } 

    @Override 
    public void set(Boolean value) { 
     getWrappedProxy().setBoolean(value); 
    } 

} 

...和...整數

public class RemoteIntegerBuilder extends RemoteVariable<Integer> implements RemoteVariableBuilder { 

    public RemoteIntegerBuilder(RemoteDeviceProxy wrappedProxy) { 
     super(wrappedProxy); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    public <T> RemoteVariable<T> buildNewVariable(RemoteDeviceProxy wrappedProxy) { 
     return (RemoteVariable<T>) new RemoteIntegerBuilder(wrappedProxy); 
    } 

    @Override 
    public Integer get() { 
     return getWrappedProxy().getInteger(); 
    } 

    @Override 
    public void set(Integer value) { 
     getWrappedProxy().setInteger(value); 
    } 

} 

其實日食產生的大部分代碼一旦知道基地類和接口。

的最後一步是創建一個工廠

public class RemoteVariableFactory { 
    private static final Map<String, RemoteVariableBuilder> BUILDERS = new HashMap<>(); 

    static { 
     BUILDERS.put(Boolean.class.getName(), new RemoteBooleanVariable(null)); 
     BUILDERS.put(Integer.class.getName(), new RemoteIntegerBuilder(null)); 
     // add more builders here 
    } 

    public static <T> RemoteVariable<T> getRemoteVariable(RemoteDeviceProxy wrappedProxy, Class<T> typeClass) { 
     RemoteVariableBuilder remoteVariableBuilder = BUILDERS.get(typeClass.getName()); 

     if (remoteVariableBuilder == null) { 
      return null; // or throw an exception whichever is better in your case 
     } 
     return remoteVariableBuilder.buildNewVariable(wrappedProxy); 
    } 
} 

現在我們已經準備好創建新RemoteVariables ...

RemoteVariable<Boolean> var1 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Boolean.class); 
RemoteVariable<Integer> var2 = RemoteVariableFactory.getRemoteVariable(new RemoteDevice(), Integer.class); 

要結束這讓我們做一個快速的比較Eng的答案。福阿德:

缺點:

  • 你需要創建一個新的類爲每次提供的數據類型

優勢:

  • 你只需要一個行添加到靜態並且在RemoteVariable中沒有兩個新的if塊到getter和setter
  • get和set不要每次都必須通過if-else-blocks