2013-03-23 38 views
2

我會用一個例子來解釋。我的GWT項目有一個公司模塊,它允許用戶添加,編輯,刪除,選擇和列出公司。看似多餘的事件和事件處理程序

其中,添加,編輯和刪除操作在CompanyList頁面上返回用戶。因此,有三個不同的事件 - CompanyAddedEvent, CompanyUpdatedEvent and CompanyDeletedEvent,以及它們各自的事件處理程序 - 對我來說看起來有點矯枉過正,因爲它們的功能絕對沒有區別。

可以讓一個事件管理這三個操作嗎? 我想一個替代方法是使用CompanyListInvokedEvent等事件。然而,我認爲它不合適的地方是事件實際上不是被調用的列表,而是一個正在被添加/更新/刪除的公司。

如果它只是一個單一的模塊,我會完成任務與三個單獨的事件。但其他10個這樣的模塊正面臨着這種困境。它意味着10x3 = 30個事件類別以及30個相應的處理程序。這個數字足以讓我重新考慮。 這將是一個很好的解決方案?

更新 -

@ ColinAlworth的回答讓我意識到,我可以很容易地使用仿製藥,而不是我笨的解決方案。以下代碼表示一個事件EntityUpdatedEvent,每當實體更新時都會引發該事件。

事件處理程序類 -

public class EntityUpdatedEvent<T> extends GwtEvent<EntityUpdatedEventHandler<T>>{ 

    private Type<EntityUpdatedEventHandler<T>> type; 
    private final String statusMessage; 

    public EntityUpdatedEvent(Type<EntityUpdatedEventHandler<T>> type, String statusMessage) { 
     this.statusMessage = statusMessage; 
     this.type = type; 
    } 

    public String getStatusMessage() { 
     return this.statusMessage; 
    } 

    @Override 
    public com.google.gwt.event.shared.GwtEvent.Type<EntityUpdatedEventHandler<T>> getAssociatedType() { 
     return this.type; 
    } 

    @Override 
    protected void dispatch(EntityUpdatedEventHandler<T> handler) { 
     handler.onEventRaised(this); 
    } 
} 

事件處理接口 -

public interface EntityUpdatedEventHandler<T> extends EventHandler { 
    void onEventRaised(EntityUpdatedEvent<T> event); 
} 

添加處理程序事件總線 -

eventBus.addHandler(CompanyEventHandlerTypes.CompanyUpdated, new EntityUpdatedEventHandler<Company>() { 

    @Override 
    public void onEventRaised(EntityUpdatedEvent<Company> event) { 
     History.newItem(CompanyToken.CompanyList.name()); 
     Presenter presenter = new CompanyListPresenter(serviceBundle, eventBus, new CompanyListView(), event.getStatusMessage()); 
     presenter.go(container); 
    } 
}); 

同樣,我有兩個其他的添加和刪除通用事件,從而消除了與事件相關的代碼庫的全部冗餘。

對此解決方案有任何建議嗎?

P.S. >This discussion提供有關此問題的更多信息。

回答

4

要回答這個問題,讓我先提出另一種思考同樣類型問題的方式 - 而不是事件,我們只是使用方法。

在我的層次的應用,兩個模塊通過接口進行通信(請注意,這些方法都是void,所以他們比較喜歡的活動 - 調用方不指望一個答案回):

package com.acme.project; 

public interface CompanyServiceInteface { 
    public void addCompany(CompanyDto company) throws AcmeBusinessLogicException; 

    public void updateCompany(CompanyDto company) throws AcmeBusinessLogicException; 

    public void deleteCompany(CompanyDto company) throws AcmeBusinessLogicException; 
} 

這看起來對我來說過分誇大 - 爲什麼不把這個API的大小減小到一個方法,並添加一個枚舉參數來簡化這個。這樣,當我構建一個替代實現或需要在單元測試中嘲笑這一點時,我只需要一種方法來構建而不是三個。當我完成我的應用程序的其餘部分時,這會變得明顯過火 - 爲什麼不只是ObjectServiceInterface.modify(Object someDto, OperationEnum invocation);可以用於所有10個模塊?


一個答案是,你可能要要大幅修改一個而不是其他的實現 - 現在你已經減少這隻有一個方法,所有這一切都屬於那個開關盒內。另一個是,一旦這樣簡化,傾向往往進一步簡化 - 可能將createupdate合併爲一種方法。一旦完成,所有的電話都必須確保完成該方法合同的所有可能的細節,而不僅僅是一個特定的細節。

如果這些事件的接收者很簡單並且仍然如此,那麼可能沒有理由不讓一個單一的ModelModifiedEvent明確地適用於所有可能的用例 - 也許只是包裝ID以請求所有客戶端模塊刷新其對象的視圖。如果未來的用例出現在只有一種事件很重要的情況下,現在事件必須改變,因爲所有導致事件被創建的站點都必須正確地填充這個新的字段。

Java商店通常不使用Java,因爲它是最漂亮的語言,也可能是因爲它是編寫或查找開發人員的最簡單的語言,但因爲維護和重構相對容易。設計API時,考慮將來的需求非常重要,而且要考慮修改當前API需要做些什麼 - 您的IDE幾乎肯定有快捷鍵來查找特定方法或構造函數的所有調用,從而允許您很容易找到所使用的所有地方並更新它們。因此,請考慮您期望的其他用例,以及可以如何輕鬆地完成代碼庫的其餘部分。

最後,別忘了泛型 - 對於我上面的示例,我可能會創建一個DtoServiceInterface來簡化問題,以便我只用三種方法聲明一個接口,然後根據需要實現它並引用它。以同樣的方式,您可以製作一組三個GwtEvent類型(同時使用*Handler接口,也可能使用Has*Handlers),但請保持它們適用於所有可能類型。以com.google.gwt.event.logical.shared.SelectionEvent<T>爲例 - 在這種情況下,您可能希望將模型對象類型作爲參數,以便處理程序可以檢查它們正在處理的事件類型(請記住泛型在Java中被刪除),或者源自一個EventBus爲每種模型類型。

+0

啊啊...... +2爲枚舉的想法:) – 2013-03-23 19:15:58

+0

@Baadshah是公平的,我不確定這是一個*好*的想法 - 但它是*一個*想法。 – 2013-03-23 20:47:45

+0

是的,可能是我們通過使用EventType enum構建了30多個演示程序應用程序和10個處理程序。使用EventType enum.Did'nt發現任何困難,無論是性能和開發side.let有人在這裏抓到我們:) – 2013-03-23 21:35:27