2015-10-14 41 views
4

這個問題更多地是針對範式。爲什麼我們不在MVP環境中使用事件總線而不是監聽器?通常,「P」部分具有視圖和模型引用的依賴注入。當然,這具有通過演示者顯示視圖和模型之間明確的契約的優點,這更易讀。MVP ::事件總線模式而不是偵聽器

但是,如果讓演示者監聽來自視圖的事件並且事件攜帶視圖有效載荷(例如:json表示),是不是一種更簡潔的方法。演講者回想起這個觀點的情況也是如此。視圖將監聽演示者的事件。主要優點是,我們不必爲視圖和演示者之間的每個合約編寫界面。如果你看看code,你會看到主持人正在接觸到查看詳細信息,如文本字段,我相信這會增加視圖和演示者之間的耦合。說,如果我要更換前端JavaFx而不是Vaadin,那麼我將不得不更改演示者。

該課程是一個實時項目的例子。在這裏,我們有不同類型的事件,即我不會創建不同情況下的事件類。例如:LoginViewEvent,DashBoardEvent等,我認爲這是一個維護的痛苦。

public class UrayEvent { 

    public static enum EventType { 

     SESSION_SELECTED(1), 
     DOCUMENT_SELECTED(2), 
     DOCUMENT_EDIT_COMPLETE(3), 
     DOCUMENT_EDIT_CANCELED(4), 
     SHOW_SESSION_TABLES(5), 
     SHOW_SESSION_DOCUMENTS(6), 
     SHOW_SESSION_COLLABORATORS(7), 
     USER_REQUESTED_REFRESH(8), 
     AUTO_REFRESH(9), 
     TABLE_SELECTED(10), 
     DETACHED(11), 
     SCHEDULER_NAVIGATION(12), 
     JIRA_USER_SELECTED(13), 
     DOCUMENT_SAVE_SUCCESS(14), 
     DOCUMENT_SAVE_FAILURE(14); 

     private final int value; 

     private EventType(int value) { 

      this.value = value; 
     } 

     public int getValue() { 

      return value; 
     } 
    } 

    public static class Event { 

     private final EventType type; 
     private final Object payload; 

     public Event(EventType type, Object eventPayload) { 

      this.type = type; 
      this.payload = eventPayload; 
     } 

     public EventType getEventType() { 

      return type; 
     } 

     public Object getEventPayload() { 

      return payload; 
     } 
    } 

} 

夠簡單了,認爲發送事件DOCUMENT_EDIT_COMPLETE .The主持人層處理這一事件。我發現這種方式,更好地將演示者的視圖分離出來。

@Subscribe 
    public void handle(UrayEvent.Event event) { 

     switch (event.getEventType()) { 
      case DOCUMENT_EDIT_COMPLETE: 
        // event payload contains document model data 
        // like document id etc 
       saveDocument(event.getEventPayload);  
       break; 
      default: 
       break; 
     } 
    } 

優勢

  • 更少鍋爐板代碼,對於n-視圖我們不需要正接口
  • 新事件意味着添加事件元件ENUM和更新相應 訂閱方法處理這個事件。

缺點,如果我們忘記從eventbus註銷

  • 內存泄漏(面對它足夠的時間)

問題

1)這種方法意味着,隨着應用程序的增長,會有更大的set枚舉元素。這種方法是反模式嗎?

2)正如我們看到它廣泛使用事件總線,有使用總線系統而不是接口監聽器模式的 的任何缺點?

在這方面想要寶貴的建議。主要問題是,如果我在整個項目中廣泛地盲目應用這種模式,我不應該後悔這樣做,那麼這種方法可能會出現什麼錯誤。

+1

隨着MVC模式和Web,你會得到問題,每個驗證/事件觸發到服務器的往返。當你使用觸發器時,一些可以直接在客戶端執行(例如字段驗證),從而防止往返。但是,是的,你在某些情況下複製代碼... –

回答

2

1)此方法意味着,隨着應用程序的增長,會有更大的set枚舉元素。這種方法是反模式嗎?

如果有很多事件需要許多事件標識符。它們可以是簡單的int s或enum s或Interface s。

您演示的機制很簡單,適用於小型應用程序。它已經被多次框架證明了很多次。以微軟的Win32 APIMFC爲例。

在一些項目中,我看到事件攔截器使用Annotation來實現,它爲處理事件提供了一個很好的方法。前一次是在利用Apache Wicket框架的項目中。

2)正如我們看到它廣泛使用事件總線,是否有使用總線系統而不是接口偵聽器模式的 的缺點?

它在不同的包中基本上是相同的東西。在Java世界中,使用監聽器接口是事實上的標準。以SwingAndroid爲例。

事件總線方法用於Facebook基於Javascript的React框架。注意到Model-View-Presenter和Flux設計模式的相似性很有趣。特別是單向數據流在兩種體系結構中都突出顯示。

您提到了將JavaFx替換爲Vaadin作爲UI框架的用例。在我看來,改變用戶界面框架,以便你能夠重複使用即使其中的一部分也很少發生。我不會僅僅因爲框架可能發生變化而付出增加抽象層和複雜性的代價。你應該從KISS和YAGNI原則開始。如果你想稍後改變UI框架,那麼你只需從頭開始再次實現UI層。