2010-05-22 27 views
3

實現一個接口的最佳方式是以各種指定方式組合相同接口的一些實例?我需要爲多個接口執行此操作,並且我希望最小化樣板並仍然實現高效率,因爲我需要這樣的關鍵生產系統。編程實現一個接口,以各種指定方式組合相同接口的一些實例

這是一個問題的草圖。

在思想上,我有一個通用的組合類需要實例,並指定不同的組合子:

class Combiner<I> { 
    I[] instances; 

    <T> T combineSomeWay(InstanceMethod<I,T> method) { 
    // ... method.call(instances[i]) ... combined in some way ... 
    } 

    // more combinators 
} 

現在,讓我們說,我想實現在許多其他如下界面:

Interface Foo { 
    String bar(int baz); 
} 

我想最終得到這樣的代碼:

class FooCombiner implements Foo { 
    Combiner<Foo> combiner; 

    @Override 
    public String bar(final int baz) { 
    return combiner.combineSomeWay(new InstanceMethod<Foo, String> { 
     @Override public call(Foo instance) { return instance.bar(baz); } 
    }); 
    } 
} 

現在,這可以如果接口有很多方法,就會很快變長。我知道我可以使用Java反射API中的動態代理來實現這樣的接口,但通過反射訪問方法的速度要慢上百倍。那麼在這種情況下,樣板和反思有什麼選擇?

+0

這是一個相當大的標題! – Secko 2010-05-22 00:41:36

回答

2

我會建議動態代理 - 它真的比現在常規的方法調用速度慢得多 - 我聽說反射在封面下有相當多的魔法來加速重複的方法調用。 (如果它是100倍慢,你確定你會注意到嗎?好吧,只需重新讀你的問題 - 你會注意到!)

否則,你基本上有你的問題的解決方案:使用Command對象在界面中包裝每種方法。然後,您可以將接口集合中的每個實例傳遞給命令對象進行處理。當然,如果你感覺勇敢和冒險,你可以使用cglib,javassist或orther dynamic bytecode generator來生成命令對象的實現,以及使用動態類生成的組合器接口的實現。這將避免樣板。

您也可能在某些方面取得了成功,尤其是具有編譯時或加載時編織方面的aspectJ,因此您可以避免反射開銷。對不起,我不能提供細節。

+0

我結束了使用動態代理,它更乾淨。另外,減速並不明顯,因爲方法訪問速度很快。 – namin 2010-05-28 15:59:47

1

你可以扭轉你的組合:

@Override 
public String bar(int baz) 
{ 
    //for (Foo f:combiner.combineSomeWay())// returns Iterator<Foo> 
    for (Foo f:combiner) //combiner must implement Iterable<Foo> or Iterator<Foo> 
    { 
     // In case of several ways to combine 
     // add() method should call some temp object 
     // in combiner created (or installed) by 
     // combineSomeWay. 
     // The best temp object to use is Iterator 
     // returned by combiner.combineSomeWay(); 
     combiner.add(f.bar(baz));// or addResult, or addCallResult 
    } 
    // clear (or uninstall) temp object and result 
    // thats why get* method 
    // name here is bad. 
    return combiner.done(); 
} 

不是一個襯墊,但更容易理解。如果你的方法拋出異常,那將會更復雜。你將需要try/catch塊和addException方法。

+0

不是一個壞主意,但它不適用於我的情況,因爲我希望組合器決定是否調用方法(例如,一個組合器只是調用第一個實例的方法而忽略其他方法)。無論如何,謝謝你的好轉。 – namin 2010-05-22 11:09:19

+0

這正是我在這裏使用迭代器而不是集合的原因。組合器必須在需要調用方法時通過迭代器提供對象,並且它可以根據add方法的參數決定Iterator將返回的下一個元素。這些延續將會大大簡化組合器,但是java還不支持它們。 – 2010-05-22 13:09:51

+0

啊,這很聰明...無論如何,在每種方法中都有一個for循環,這仍然是非常有趣的。但好戲。 – namin 2010-05-28 16:00:52

相關問題