MVP ::事件总线模式而不是监听器

时间:2015-10-14 08:07:01

标签: java c++ design-patterns vaadin guava

这个问题更倾向于范式。为什么我们在MVP环境中不使用事件总线而不是听众?通常," P" part具有依赖注入视图和模型引用。当然,这有利于通过演示者在视图和模型之间显示明确的契约,这更具可读性。

然而,让演示者从视图和事件中侦听事件会带来视图有效负载(例如:json表示),这不是一种更干净的方法。主持人回复视图的情况也是如此。 View将监听演示者发布的事件。主要优点是,我们不必为视图和演示者之间的每个合同编写接口。如果您查看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 。演示者层处理此事件。我找到了这种方式,这是一种更好的方法来从演示者中分离视图。

    @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视图,我们不需要n接口
  • 新事件表示将事件元素添加到枚举并更新各自 订阅处理此事件的方法。

缺点

  • 如果我们忘记从eventbus取消注册(面对足够的时间),内存泄漏

问题

1)这种方法意味着,随着应用程序的增长,会有更大的set枚举元素。这种方法是反模式吗?

2)正如我们所看到的,它广泛使用事件总线有任何缺点 使用总线系统而不是接口监听模式?

在这方面想要你宝贵的建议。主要问题是,如果我在整个项目中盲目地应用这种模式,我不应该后悔这样做,这种方法可能存在什么陷阱。

1 个答案:

答案 0 :(得分:2)

  

1)这种方法意味着,有更大的集合枚举元素作为   应用程序增长这种方法是反模式吗?

如果有很多事件,您需要许多事件标识符。它们可以是简单的intenumInterface s。

您演示的机制很简单,适用于小型应用程序。已经多次使用多个框架证明了这一点。以微软的Win32 APIMFC

为例

在某些项目中,我看到用Annotation实现的事件拦截器为处理事件提供了一种优雅的方式。上一次是在使用Apache Wicket框架的项目中。

  

2)正如我们所看到的,它广泛使用事件总线有任何缺点   使用总线系统而不是接口监听模式?

在不同的包中基本上是一样的。在Java世界中,使用侦听器接口是事实上的标准。以SwingAndroid为例。

事件总线方法用于Facebook基于Javascript的React框架。有趣的是注意到Model-View-Presenter和Flux设计模式的相似性。特别是单向数据流在两种架构中都突出显示。

您提到了将JavaFx替换为Vaadin作为UI框架的用例。在我看来,更改UI框架,以便您甚至可以重复使用它的某些部分。我不会因为框架可能会改变而预先支付增加的抽象层和复杂性的代价。相反,你应该从KISS和YAGNI原则开始。如果您想稍后更改UI框架,那么您只需从头开始再次实现UI层。