Этот вопрос больше к парадигме. Почему мы не используем Event Bus вместо слушателей в среде MVP? Как правило, часть «P» имеет внедрение зависимости представления и ссылок на модель. Конечно, у этого есть преимущество, заключающееся в явном заключении контракта между представлением и моделью через презентатора, что является более читабельным.
Однако не будет ли более чистый подход, чтобы докладчик прослушивал события из представлений, а события несут полезную нагрузку представления (например, представление json). То же самое и в случае с докладчиком, обращающимся к представлению. Просмотр будет слушать события от ведущего. Главное преимущество в том, что нам не нужно писать интерфейсы для каждого контракта между представителем и докладчиком. Если вы посмотрите на код вы увидите, что докладчик получает доступ к деталям просмотра, таким как текстовые поля, что, как я считаю, увеличивает связь между представлением и докладчиком. Скажем, если я заменю внешний интерфейс 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;
}
}
преимущество
Недостаток
Вопросы
1) Этот подход означает, что по мере роста приложения будут заданы более крупные элементы enum. Является ли этот подход анти-паттерном?
2) Как мы видели, он широко использует Event Bus, есть ли недостатки
используя систему шин вместо шаблона интерфейса слушателя?
Разыскивается ваше ценное предложение на этот счет. Основная проблема заключается в том, что, если я слепо широко применяю этот шаблон в проекте, я не должен сожалеть об этом, что может быть возможным подводным камнем в этом подходе.
1) Этот подход означает, что в качестве
приложение растет. Является ли этот подход анти-паттерном?
Если есть много событий, вам нужно много идентификаторов событий. Они могут быть простыми int
с или enum
с или Interface
s.
Механизм, который вы продемонстрировали, прост и хорошо работает с небольшими приложениями. Это было доказано много раз с несколькими структурами. Взять к примеру Microsoft Win32 API
а также MFC
,
В некоторых проектах я видел перехватчики событий, реализованные с Annotation
s, который обеспечивает элегантный способ обработки событий. Предыдущий раз был в проекте с использованием Apache Wicket
фреймворк.
2) Как мы видели, он широко использует Event Bus, есть ли недостатки
используя систему шин вместо шаблона интерфейса слушателя?
Это в основном то же самое в другой упаковке. В мире Java де-факто стандартно использовать интерфейсы слушателей. Возьмите например Swing
а также Android
,
Подход к шине событий используется в Facebook на основе Javascript React
фреймворк. Интересно отметить сходство шаблонов проектирования Model-View-Presenter и Flux. В частности, однонаправленный поток данных выделяется в обеих архитектурах.
Вы упомянули случай использования замены JavaFx
с Vaadin
в качестве основы пользовательского интерфейса. На мой взгляд, изменение фреймворка пользовательского интерфейса, чтобы вы могли использовать его даже в некоторых случаях, происходит очень редко. Я бы не стал платить цену за добавленные уровни абстракции и сложности заранее, потому что структура может измениться. Скорее вы должны начать с принципов KISS и YAGNI. Если вы хотите изменить структуру пользовательского интерфейса позже, вы просто снова внедрите уровень пользовательского интерфейса с нуля.
Других решений пока нет …