Этот пост должен идти как предисловие к серии постов Реализуем EventPublisher. Но хорошая мысль, как это с ней часто бывает, пришла позже. :) Поэтому о назначении (читай решаемых проблемах) шаблона Event Aggerator расскажу только сейчас.
Для начала понадобиться пример проблемы. Пусть есть некое приложение c архитектурой MVVM. Скажем, модель для главного меню может выглядеть примерно так:
Решение: Необходим единый способ диспетчеризации событий главного меню, т.е. Event Aggregator. Напомню основные его интерфейсы:
1. Определить необходимые сообщения:
Для начала понадобиться пример проблемы. Пусть есть некое приложение c архитектурой MVVM. Скажем, модель для главного меню может выглядеть примерно так:
public class MainMenuVewModel { public MainMenuVewModel( IClientsViewModel clientsViewModel, ICountriesViewModel countriesViewModel, ICitiesViewModel citiesViewModel, IWindowManager windowManager) { _clientViewModel = clientsViewModel; _countriesViewModel = countriesViewModel; _citiesViewModel = citiesViewModel; _windowManager = windowManager; } public void ShowClients() { _windowManager.Show(_clientsViewModel); } public void ShowCounrties() { _windowManager.Show(_clientsViewModel); } public void ShowCities() { _windowManager.Show(_clientsViewModel); } }Проблема: Этот код не так уже плох, но это может быть далеко не полным перечнем всех зависимостей, которые понадобятся нашему меню. Это затрудняет его понимание, и не очень хорошо для тестирования. Ведь для модульного теста придётся написать как минимум 4 мок-объекта. Хотелось бы более элегантный способ, который бы не требовал каждый раз добавлять новую зависимость для нового пункта меню, что включает в себя как минимум три действия (объявление члена класса, объявление параметра конструктора, создание нового метода).
Решение: Необходим единый способ диспетчеризации событий главного меню, т.е. Event Aggregator. Напомню основные его интерфейсы:
public interface IPublisher { void Publish<TMessage>(TMessage message); } public interface IListener<TMessage> { void ListenTo(TMessage message); }Что же с ними делать? Давайте по порядку:
1. Определить необходимые сообщения:
public class ShowClientsMessage {} public class ShowCountriesMessage {} public class ShowCitiesMessage {}2. Переписать модель главного меню с помощью IPublisher.
public class MainMenuVewModel { public MainMenuVewModel(IPublisher publisher) { _publisher = publisher; } public void ShowClients() { _publisher.Publish(new ShowClientsMessage()); } public void ShowCounrties() { _publisher.Publish(new ShowCountriesMessage()); } public void ShowCities() { _publisher.Publish(new ShowCitiesMessage()); } }3. Написать обработчики событий:
public class ShowViewModelListener : TransientListenter<ShowClientsMessage> { public MainMenuVewModel(IWindowManager windowManager, IClientsViewModel clientsViewModel) { _windowManager = windowManager; _clientsViewModel = clientsViewModel; } public void Handle(ShowClientsMessage message) { _windowManager.Show(_clientsViewModel); } } // обработчики двух других событий выглядят идентично, для краткости их не привожу.Что в итоге? Мы получили более простую модель главного меню за счёт вынесения сложности на другие классы. Сложность системы несколько увеличилась, но вместе с тем увеличилась и ее гибкость. Стоит ли игра свеч решать вам.
Комментариев нет:
Отправить комментарий