Шаблон проектирования Посредник — Mediator

Десятый шаблон в серии Design Patterns.

Посредник — суть в том, чтобы иметь слабую связь между абстрактными объектами и иметь возможность переопределять конкретные реализации, причем иметь явную связь и инкапсулированное взаимодействие.

Все станет ясней, когда мы перейдем от слов к коду.

Во многих источниках приводится пример чата, когда есть несколько участников чата и любой из них может отправить сообщение и естественно это сообщение должны получить все, кроме отправителя. Здесь явная связь между отправителем и получателем и можно вынести этот механизм в абстрактный класс и интерфейс. А как именно получать сообщения, точнее что с ними делать при получении уже решать в конечных реализациях.

Я же решил придумать иной пример. Предположим у нас некая игра, в которой участвуют несколько игроков. У каждого есть определенное количество единиц здоровья и сила, с которой он может ударить других участников. И при каждом его ходе он атакует всех, кроме себя (здесь кстати можно еще разделить участников на группы и не атаковать «своих»).

Как мне кажется для этой ситуации данный шаблон вполне подходит. Давайте рассмотрим главный интерфейс посредника.

Здесь у нас 1 метод отправки (атаки), где мы укажем объем урона и игрока, который его инициирует. Рассмотрим абстрактный класс пользователя.

Класс отправитель или пользователь имеет в себе ссылку на посредника, которую задаем через конструктор. Также имеем конкретный метод отправки (атаки), в котором указываем только размер урона и вызываем аналогичный метод у посредника, указывая текущего пользователя. Но кроме того, что наш игрок отправляет событие (атакует), он также получает урон, но мы объявляем этот метод абстрактным.

Теперь у нас есть слабая связь между посредником и юзером. Нам осталось создать конкретного посредника, где мы определим метод отправки события (атака) и создать конкретный класс игрока, где мы будем получать урон.

Рассмотрим класс посредника.

Здесь у нас список игроков, метод добавления игрока в список и самое интересное, имплементация метода отправки(атаки), мы проходим через весь список и если мы имеем дело не с тем игроком, который вызывает этот метод, то получаем урон.

Нам нужна некая информация по игроку, какой у него запас жизни, какой урон он может наносить и имя. Для этого создадим некий класс, который может хранить эту информацию.

Также нам нужен метод, который будет уменьшать количество здоровья у игрока и в какой-то момент игрок должен умереть. Для этого будем отслеживать состояние через булевскую переменную.

А теперь рассмотрим конкретного игрока.

При создании передадим игроку всю информацию и при получении урона (receive) будем уменьшать здоровье (decreaseHealth).

Теперь, чтобы это все посмотреть в действии давайте создадим экран со списком участников.

Нам нужен адаптер для списка.

При создании адаптера просто передадим список данных участников. В конструкторе создаем посредника, наполняем игроками. Когда игрок будет атаковать других будем вызывать метод send и передадим объем урона, после чего просто обновим экран с данными.

Элемент с данными игрока выглядит так

Отобразим имя игрока и какой у него урон, сколько осталось здоровья и кнопку, по которой он атакует других. Если у игрока не осталось здоровья, то отображаем что он мертв и при нажатии на кнопку атаки ничего не должно произойти (можно бы было просто убирать мертвых из списка).

Главный экран выглядит максимально просто. Вот разметка

И сам код

И давайте протестируем и посмотрим кто из игроков останется в живых, если они будут по очереди сверху вниз атаковать друг друга.

Что интересно, если бы игроки атаковали снизу вверх, все равно в живых бы остался игрок номер 2.

Итак, плюсы шаблона

Слабая связь между классом и посредником, возможность иметь разные реализации как посредника так и главного класса.

Минусы — некоторая сложность понимания в начале, потому как у главного класса вызывается метод, который дергает метод у посредника, а тот уже в свою очередь выполняет вызов другого метода у главного метода с некоторыми условиями.

 

Запись опубликована в рубрике Программирование Android, Программирование Java. Добавьте в закладки постоянную ссылку.