2013-04-02 70 views
0

我有一個實現接口的類。還有另外一個類實現了這個接口,這個第二類的實例支持我的類的實現。如何減少委託樣板文件?

對於接口指定的許多方法,我的類只是將它們直接轉發給第二類。

public class MyClass implements MyInterface 
{ 
    private OtherClass otherClassInstance; // Also implements MyInterface. 
    // ... 
    void foo() { otherClassInstance.foo(); } 
    void bar() { otherClassInstance.bar(); } 
    void baz() { otherClassInstance.baz(); } 
    // ... 
} 

只需從第二類派生我的課就消除了這一切,但它沒有任何意義,因爲這兩個類是彼此無關(除了實現通用接口)。它們代表了不同的東西 - 恰恰相反,我的課程的很多實現複製了其他課程的實施。換句話說,我的課程是在第二課堂上實施的,但它本身並不是第二課程的一部分。正如我們所知,繼承意味着表達一種「是 - 一種」的關係,而不是共享實現,所以在這種情況下它是不合適的。

This約書亞布洛赫談話的一部分很好地說明了這種情況。

我知道Java對代表團沒有任何語言支持。但是,至少有一些方法來清理我的類的實現,所以它不是多餘的?

+0

讓我們直...你想擴展ArrayList,但不是在任何情況下,但一個接口不會削減它... 它你的'MyList'下降到主要是ArrayList那麼它真的會有意義擴展ArrayList,並相應地處理非數組列表。 – Shark

+0

通常我會檢查「MyList」的原因。大多數情況下,它是一個ArrayList,在某些情況下我需要特殊的行爲。對於這種情況,我使用ArrayList並構建Wrapper/Adapter /命令來提供功能。大部分時間我都會查看番石榴,並免費獲得所需的延期。 –

+0

@Shark不,我不想擴展'ArrayList'。我讓我自己的類實現'List','ArrayList'成員只支持我的實現。它對* MyList對象用來代替'ArrayList'對象是沒有意義的 - 永遠不會。 – Maxpm

回答

3

的回答這是不是一個真正的答案,你的實際問題:

我會說,生活與樣板。讓IDE爲您生成它。例如:在Netbeans中,添加私有ArrayList字段,將光標設置到您希望方法出現的位置,按Alt-Insert,選擇「生成委託方法...」,單擊要創建委託的方法因爲在對話框打開,提交,通過生成的方法,並使他們做正確的事情,你就完成了。

這有點難看,但是當你僅僅處理一個類時,就像開始聽起來一樣,它開始混淆反射仍然是可取的。你的班級可能是那種班級,你會完成並完全測試,然後希望不要再碰。反射會創建不會消失的運行時成本。在這種情況下,在源文件中遭遇自動生成的樣板文件可能更可取。

+0

關於性能的好處。 – Maxpm

+1

反射很混亂,容易出錯,並在運行時爆炸。 – Jazzepi

1

使用第一種方式http://java.sun.com/javase/6/docs/api/java/lang/reflect/Proxy.html參見教程http://docs.oracle.com/javase/1.4.2/docs/guide/reflection/proxy.html

使用AOP可以創建調度員是攔截特定類

的所有調用對於需要使用反射API

管理方法處理兩種方式

方式二

編輯展示IDEA 以上代碼取自上面的代碼只是稍微修改了一下(參見invoke方法中的youListImpl.getRealArrayList())

public class DebugProxy implements java.lang.reflect.InvocationHandler { 

    private YouListImpl youListImpl; 

    public static Object newInstance(Object obj) { 
    return java.lang.reflect.Proxy.newProxyInstance(
     obj.getClass().getClassLoader(), 
     obj.getClass().getInterfaces(), 
     new DebugProxy(obj)); 
    } 

    private DebugProxy(Object obj) { 
    this.obj = obj; 
    } 

    public Object invoke(Object proxy, Method m, Object[] args) 
    throws Throwable 
    { 
     Object result; 
    try { 
     System.out.println("before method " + m.getName()); 
     result = m.invoke(youListImpl.getRealArrayList(), args); 
     } catch (InvocationTargetException e) { 
     throw e.getTargetException(); 
     } catch (Exception e) { 
     throw new RuntimeException("unexpected invocation exception: " + 
         e.getMessage()); 
    } finally { 
     System.out.println("after method " + m.getName()); 
    } 
    return result; 
    } 
} 
+0

您能否提供具體的反射API如何在這種情況下使用的例子? – Maxpm

+0

@Maxpm只是放置一個快照 – Dewfy