Паттерн «Посредник» (Mediator)
Назначение: Паттерн Посредник (Mediator) представляет такой шаблон проектирования, который обеспечивает взаимодействие множества объектов без необходимости ссылаться друг на друга. Тем самым достигается слабосвязанность взаимодействующих объектов.
Другими словами: посредник — это клей, связывающий несколько независимых классов между собой. Он избавляет классы от необходимости ссылаться друг на друга, позволяя тем самым их независимо изменять и анализировать.
Когда используется паттерн Посредник?
-
Когда имеется множество взаимосвязаных объектов, связи между которыми сложны и запутаны.
-
Когда необходимо повторно использовать объект, однако повторное использование затруднено в силу сильных связей с другими объектами.
UML схема паттерна Mediator:
Реализация шаблона на .NET
public abstract class Mediator
{
public abstract void Send(string msg, Colleague colleague);
}
public abstract class Colleague
{
private Mediator mediator;
public Colleague(Mediator mediator)
{
this.mediator = mediator;
}
public virtual void Send(string message)
{
mediator.Send(message, this);
}
public abstract void Notify(string message);
}
// класс заказчика
public class CustomerColleague : Colleague
{
public CustomerColleague(Mediator mediator)
: base(mediator)
{ }
public override void Notify(string message)
{
Console.WriteLine("Сообщение заказчику: " + message);
}
}
// класс программиста
public class ProgrammerColleague : Colleague
{
public ProgrammerColleague(Mediator mediator)
: base(mediator)
{ }
public override void Notify(string message)
{
Console.WriteLine("Сообщение программисту: " + message);
}
}
// класс тестера
public class TesterColleague : Colleague
{
public TesterColleague(Mediator mediator)
: base(mediator)
{ }
public override void Notify(string message)
{
Console.WriteLine("Сообщение тестеру: " + message);
}
}
public class ManagerMediator : Mediator
{
public Colleague Customer { get; set; }
public Colleague Programmer { get; set; }
public Colleague Tester { get; set; }
public override void Send(string msg, Colleague colleague)
{
// если отправитель - заказчик, значит есть новый заказ
// отправляем сообщение программисту - выполнить заказ
if (Customer == colleague)
Programmer.Notify(msg);
// если отправитель - программист, то можно приступать к тестированию
// отправляем сообщение тестеру
else if (Programmer == colleague)
Tester.Notify(msg);
// если отправитель - тест, значит продукт готов
// отправляем сообщение заказчику
else if (Tester == colleague)
Customer.Notify(msg);
}
}
Схема примера использования паттерна "посредник" в реальной жизни:
Резюме:
- «Посредник» — это один из самых распространенных паттернов проектирования. Они десятками используются в любом приложении, хотя в именах классов это практически никогда не отражается.
- В классической реализации паттерна «Посредник» независимые классы не знают друг о друге, но знают о существовании посредника и все взаимодействие происходит через него явным образом.
- Очень часто слой приложения играет роль посредника: объединяет вместе доменные и сервисные слои и обеспечивает поведение, уникальное для конкретного приложения.
Примеры реализации паттерна в .NET Framework
«Посредник» — это паттерн, который не проявляется в открытом интерфейсе модуля или библиотеки, поэтому примеры использования нужно искать в реализации .NET Framework или пользовательском коде. Тем не менее примеров использования паттерна «Посредник» в .NET-приложениях довольно много.
- В Windows Forms любая форма по своей сути представляет собой посредник, объединяющий элементы управления между собой: форма подписывается на события одного элемента управления и в случае изменения состояния уведомляет бизнес-объекты или другие элементы управления.
- Класс EventAggregator, активно используемый в WPF и за его пределами, и является примером глобального посредника для связи разных независимых компонентов между собой.
- В паттернах MVC (Model — View — Controller, «Модель — представление — контроллер») и MVP (Model — View — Presenter, «Модель — представление — презентер»), Controller и Presenter выступают в роли посредника между представлением и моделью.
- Паттерн Producer/Consumer («Поставщик»/«Потребитель») является еще одним примером паттерна «Посредник». В этом паттерне потребитель и поставщик не знают друг о друге и общаются между собой за счет общей очереди, которая является посредником. В случае .NET Framework таким посредником может служить BlockingCollection.