2009-04-21 22 views
2

我試圖爲以下問題找到一個優雅的OOP解決方案。處理具有混合POJOS的集合,每個POJO具有不同的處理函數

假設我們有一個POJOS集合,在這種情況下,每個POJO可能是不同的類。我們需要處理這個集合,對每個POJO類(或類型)使用不同的規則。

一個基本假設是我們不能用適當的處理程序來裝飾POJO,因爲我們不控制它們的生成,並按原樣接收集合。因此,任何機制都會陷入同一陷阱。但是,第3項處理這種可能性。

有一些可能的解決方案,一些非常醜陋,多了一些優雅而複雜的:

  1. 顯而易見的解決方案,以及最醜的,使用}這種運營商POJO傳遞到處理程序。
  2. 對1進行稍微更好的修改,就是對鏈式調度程序使用一個責任鏈,這樣新的類型只需要一個新的調度程序。但是,每個調度器仍然需要instanceOf。
  3. 創建增強的對象,而不是POJOS,其中每個對象都持有對其處理程序的引用。這創建了POJO和我們的處理器之間的耦合。
  4. 創建(我知道如何在Java中正確執行此操作)將處理程序註冊到特定事件類的調度程序服務,並使用泛型(類型安全容器,如有效的java中)將事件分派給處理程序。

4是最優雅的,但我想知道是否有更好的想法。

回答

4

簡化#4:

使用映射來存儲每個事件類的處理程序。

Map<Class, Handler> classHandlers = new HashMap<Class, Handler>(); 
classHandlers.put(EventA.class, new EventAHandler()); 
classHandlers.put(EventB.class, new EventBHandler()); 

現在使用事件的類來獲取事件的處理程序。

Handler handler = classHandlers.get(event.getClass()); 
handler.handle(event); 

當然,這需要在編碼時知道所有可能的事件類,因此不如外部事件調度器靈活。

+0

您將在編碼時間通知所有現有的事件類別:-) 每次添加新類時,都需要添加一個新處理程序,然後編碼... – KarlP 2009-04-21 13:19:05

+0

+1。 「這需要在編碼時間瞭解所有可能的事件類別」:對我來說,似乎是基本要求的一部分。 – Olivier 2009-04-21 13:21:18

0

我已經在這種情況下使用了第4號解決方案,我認爲它是一個很好的解決方案。我還會尋找更好的解決方案的其他意見。

0

4是您呈現的最佳解決方案。 #1 & 2將是一個混亂的instanceof漂浮在一起的痛苦。

另一種解決方案:用它的調度方法爲每個類註釋。您不需要一箇中心位置來處理調度程序調用,並且POJO /調度程序不會在註釋之外耦合。

+0

他可能無法註釋他們,因爲他不負責他們的創建,這也可能意味着它是第三方類。 – willcodejavaforfood 2009-04-21 12:01:02

1

假設我們有一個POJOS集合,這種情況下的事件,其中每個POJO可能是不同的類。我們需要處理這個集合,對每個POJO類(或類型)使用不同的規則。

恭喜如果的POJO類是穩定的(新類類型是不是經常加)你剛纔描述的動機使用訪問者模式!

更好的是,因爲你可能想要對你的POJO集合做不同的事情,你可以創建一個AbstractBaseVisitor並將其擴展以處理你需要做的不同事情!

這將需要在每個POJO周圍放置一個小包裝,並且每個POJO類都有一個包裝類,以添加一個visit()函數,該函數可以回調Visitor。

0

這個問題實際上不是語言不可知的。在某些語言中,您可以輕鬆裝飾課程。但讓我們堅持到Java。即使在那裏,我說「這取決於」。

我們想要做的一件事很明顯,就是處理程序的某種自動發現。例如,使用@Handler(handles = PojoA.class)批註註釋處理程序,然後掃描所有使用@Handler註解的類(要麼是基本上需要加載類文件的雜亂方式,要麼使用Scannotation等)。

如果您在Spring等環境中運行,則會出現更有趣的選項。你可以實現一定的接口,所有的豆類如下列:

public interface Handler<T> { 
    void handle(T object); 
} 

,然後發現他們在您的調度員代碼:

Collection<Handler> handlers = applicationContext.getBeansofType(Handler.class).values(); 
for (Handler handler : handlers) { 
    Method handleMethod = handler.getClass().getMethod("handle", Object.class); 
    Class<?> type = handleMethod.getParameterTypes()[0]; 
    register(type, handler); 
} 

(當然,上面的代碼是未經測試)

我意識到我在這裏走出了界限。我的觀點是,解決方案的高雅取決於您的選擇語言,您願意使用哪些外部工具以及您使用的是什麼框架。