2013-03-23 114 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