2012-11-14 68 views
4

我想開發一個基於處理某些事件並生成數據的系統。每個事件將包含(可能)幾個不同的字段,每個偵聽器將處理一些或他們。我心目中Java - 事件處理設計

  1. 以下兩種方法在事件代班,我會註冊多個事件監聽器,每個監聽事件的特定領域的一個特定值,例如:

    public class MicroListener implements Listener { 
    
    public void processEvent(Event e){ 
        if(e.getName().equals(registeredName)) { ... } 
    } 
    

這很誘人,因爲處理是在對象本身內完成的,沒有集中處理事件,而是允許每個對象處理信息。這個缺點可能是致命的,事實是每個事件(超過幾十萬)將不得不向所有聽衆廣播,而只有很小的一部分會真正做到這一點。它可能會產生從長遠來看有很大的性能損失...

  1. 集中式監聽器,在所有的事件,這將傾聽並採取行動,並委託處理相應的事件處理器,例如:

    public class CentralListener implements Listener { 
    
        Map<String, Processor> processorsByName; 
    
        public void processEvent(Event e){ 
         processorsByName.get(e.getName()).process(e); 
        } 
    } 
    

這會更快,但它會需要單獨的地圖或處理器的集合用於事件的任何其他部分,例如檢查事件ID等的處理器。方法1中不是這種情況,因爲我們只是生成另一組偵聽器並將它們註冊到事件生成類。

你們對這些有什麼看法?他們是有道理的,還是你會建議完全不同的?

回答

3

這是一個常見的設計決定,我不認爲有一個通用的答案是正確的所有(甚至大多數情況下)。我可以用兩種方法列出各種權衡,但它們可能很明顯。在我考慮可能的性能影響之前,我會支持任何最適合概念模型的設計(並且不會創建一堆無關的類)。

如果性能是最關心的問題,那麼使用大型開關/大小塊切換整數事件id的集中控制器可能會最快。 ...並且隨着時間的推移最不靈活/可維護。您可能想要查看Guava project's EventBus。它使用註釋來註冊事件監聽器,併爲這種類型的事件廣播/訂閱提供了一個非常乾淨的api。事件訂閱者根據他們在方法簽名中聲明的事件類型進行通知。這是非常光滑的,並節省了大量的樣板。我不知道它會如何擴展到數千種事件類型,但與一些類似的圖書館不同,事件總線不是全球性的。您可以創建不同的事件總線實例來分離事件處理,只要這樣做有意義。

0

這聽起來像你是在一個相當大的和(可能)複雜的開始。在使用你提到的兩種更重要的啓發式方法之前,我可能會仔細研究一下基於事件的編程。這個想法與使用監聽器非常相似,只是異步實現,所以事件監聽器可以是他們自己的小線程,只有當他們被要求採取行動時纔會起作用。

我不知道這裏是否適用,但我們假設你有不同的事件類型需要傳播給不同的監聽器。與其將觀察者存儲在一個巨大的堆中,爲什麼不爲每個觀察者可以註冊的事件類型創建一個監聽器?如果你有一些生成事件的核心組件,他們可以將它們發送給監聽器,再將它們發送給觀察者。

在我看來,主要好處是責任在被照顧之前委派給(子)聽衆。在一個真正可以幫助程序員的大環境中,它可以防止性能瓶頸。我相信這也被稱爲reactor pattern

如果您正在尋找靈感,請嘗試看看akka framework。它專爲高效的分佈式事件編程而設計。