Посредник (Mediator)

Последнее обновление: 31.10.2015

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

Когда используется паттерн Посредник?

  • Когда имеется множество взаимосвязаных объектов, связи между которыми сложны и запутаны.

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

Схематично с помощью UML паттерн можно описать следующим образом:

Паттерн Mediator в C# и .NET

Формальная структура классов и связей между ними с применением паттерна на языке C#:

abstract class Mediator
{
    public abstract void Send(string msg, Colleague colleague);
}

abstract class Colleague
{
    protected Mediator mediator;

    public Colleague(Mediator mediator)
    {
        this.mediator = mediator;
    }
}

class ConcreteColleague1 : Colleague
{
    public ConcreteColleague1(Mediator mediator)
        : base(mediator)
    { }
 
    public void Send(string message)
    {
        mediator.Send(message, this);
    }
 
    public void Notify(string message)
    { }
}

class ConcreteColleague2 : Colleague
{
    public ConcreteColleague2(Mediator mediator)
        : base(mediator)
    { }
 
    public void Send(string message)
    {
        mediator.Send(message, this);
    }
 
    public void Notify(string message)
    { }
}

class ConcreteMediator : Mediator
{
    public ConcreteColleague1 Colleague1 { get; set; }
    public ConcreteColleague2 Colleague2 { get; set; }
    public override void Send(string msg, Colleague colleague)
    {
        if (Colleague1 == colleague)
            Colleague2.Notify(msg);
        else
            Colleague1.Notify(msg);
    }
}

Участники

  • Mediator: представляет интерфейс для взаимодействия с объектами Colleague

  • Colleague: представляет интерфейс для взаимодействия с объектом Mediator

  • ConcreteColleague1 и ConcreteColleague2: конкретные классы коллег, которые обмениваются друг с другом через объект Mediator

  • ConcreteMediator: конкретный посредник, реализующий интерфейс типа Mediator

Рассмотрим реальный пример. Система создания программных продуктов включает ряд акторов: заказчики, программисты, тестировщики и так далее. Но нередко все эти акторы взаимодействуют между собой не непосредственно, а опосредованно через менеджера проектов. То есть менеджер проектов выполняет роль посредника. В этом случае процесс взаимодействия между объектами мы могли бы описать так:

class Program
{
    static void Main(string[] args)
    {
        ManagerMediator mediator = new ManagerMediator();
        Colleague customer = new CustomerColleague(mediator);
        Colleague programmer = new ProgrammerColleague(mediator);
        Colleague tester = new TesterColleague(mediator);
        mediator.Customer = customer;
        mediator.Programmer = programmer;
        mediator.Tester = tester;
        customer.Send("Есть заказ, надо сделать программу");
        programmer.Send("Программа готова, надо протестировать");
        tester.Send("Программа протестирована и готова к продаже");

        Console.Read();
    }
}

abstract class Mediator
{
    public abstract void Send(string msg, Colleague colleague);
}
abstract class Colleague
{
    protected 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);
}
// класс заказчика
class CustomerColleague : Colleague
{
    public CustomerColleague(Mediator mediator)
        : base(mediator)
    { }

    public override void Notify(string message)
    {
        Console.WriteLine("Сообщение заказчику: " + message);
    }
}
// класс программиста
class ProgrammerColleague : Colleague
{
    public ProgrammerColleague(Mediator mediator)
        : base(mediator)
    { }

    public override void Notify(string message)
    {
        Console.WriteLine("Сообщение программисту: " + message);
    }
}
// класс тестера
class TesterColleague : Colleague
{
    public TesterColleague(Mediator mediator)
        : base(mediator)
    { }

    public override void Notify(string message)
    {
        Console.WriteLine("Сообщение тестеру: " + message);
    }
}

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);
    }
}

Класс менеджера - ManagerMediator в методе Send() проверяет, от кого пришло сообщение, и в зависимости от отправителя перенаправляет его другому объекту с помощью методов Notify(), определенных в классе Colleague.

Консольный вывод программы:

Сообщение программисту: Есть заказ, надо сделать программу
Сообщение тестеру: Программа готова, надо протестировать
Сообщение заказчику: Программа протестирована и готова к продаже

В итоге применение паттерна Посредник дает нам следующие преимущества:

  • Устраняется сильная связанность между объектами Colleague

  • Упрощается взаимодействие между объектами: вместо связей по типу "все-ко-всем" применяется связь "один-ко-всем"

  • Взаимодействие между объектами абстрагируется и выносится в отдельный интерфейс

  • Централизуется управления отношениями между объектами

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850