Посредник (шаблон проектирования)
Из Википедии, бесплатной энциклопедии
Посредник | |
---|---|
Mediator | |
Тип | поведенческий |
Описан в Design Patterns | Да |
Посредник (англ. Mediator) — поведенческий шаблон проектирования, обеспечивающий взаимодействие множества объектов, формируя при этом слабое зацепление и избавляя объекты от необходимости явно ссылаться друг на друга.
Проблема[править | править код]
Обеспечить взаимодействие множества объектов, сформировав при этом слабую связанность и избавив объекты от необходимости явно ссылаться друг на друга.
Решение[править | править код]
Создать объект, инкапсулирующий способ взаимодействия множества объектов.
Преимущества[править | править код]
Устраняется связанность между "Коллегами", централизуется управление.
Структура[править | править код]
- Mediator – "Посредник"
- ConcreteMediator – "Конкретный посредник"
- Классы Colleague – "Коллеги"
Описание[править | править код]
"Посредник" определяет интерфейс для обмена информацией с объектами "Коллеги", "Конкретный посредник" координирует действия объектов "Коллеги". Каждый класс "Коллеги" знает о своем объекте "Посредник", все "Коллеги" обмениваются информацией только с посредником, при его отсутствии им пришлось бы обмениваться информацией напрямую. "Коллеги" посылают запросы посреднику и получают запросы от него. "Посредник" реализует кооперативное поведение, пересылая каждый запрос одному или нескольким "Коллегам".
Примеры[править | править код]
Пример на Java[править | править код]
public abstract class Colleague { protected Mediator mediator; public Colleague(Mediator mediator) { this.mediator = mediator; } public void send(String message) { mediator.send(message, this); } public abstract void notify(String message); } public abstract class Mediator { public abstract void send(String message, Colleague sender); } public class ConcreteColleague1 extends Colleague { public ConcreteColleague1(Mediator mediator) { super(mediator); } @Override public void notify(String message) { System.out.println("Colleague1 gets message: " + message); } } public class ConcreteColleague2 extends Colleague { public ConcreteColleague2(Mediator mediator) { super(mediator); } @Override public void notify(String message) { System.out.println("Colleague2 gets message: " + message); } } public class ConcreteMediator extends Mediator { private ConcreteColleague1 colleague1; private ConcreteColleague2 colleague2; public void setColleague1(ConcreteColleague1 colleague) { this.colleague1 = colleague; } public void setColleague2(ConcreteColleague2 colleague) { this.colleague2 = colleague; } @Override public void send(String message, Colleague sender) { if (sender.equals(colleague1)) { colleague2.notify(message); } else { colleague1.notify(message); } } } public class Main { public static void main(String[] args) { ConcreteMediator m = new ConcreteMediator(); ConcreteColleague1 c1 = new ConcreteColleague1(m); ConcreteColleague2 c2 = new ConcreteColleague2(m); m.setColleague1(c1); m.setColleague2(c2); c1.send("How are you?"); c2.send("Fine, thanks"); } }
Пример на C#[править | править код]
// Mediator pattern — Structural example using System; namespace DoFactory.GangOfFour.Mediator.Structural { /// <summary> /// MainApp startup class for Structural /// Mediator Design Pattern. /// </summary> class MainApp { /// <summary> /// Entry point into /// </summary> static void Main() { ConcreteMediator m = new ConcreteMediator(); ConcreteColleague1 c1 = new ConcreteColleague1(m); ConcreteColleague2 c2 = new ConcreteColleague2(m); m.Colleague1 = c1; m.Colleague2 = c2; c1.Send("How are you?"); c2.Send("Fine, thanks"); // Wait for user Console.ReadKey(); } } /// <summary> /// The 'Mediator' abstract class /// </summary> abstract class Mediator { public abstract void Send(string message, Colleague colleague); } /// <summary> /// The 'ConcreteMediator' class /// </summary> class ConcreteMediator : Mediator { public ConcreteColleague1 Colleague1 { private get; set; } public ConcreteColleague2 Colleague2 { private get; set; } public override void Send(string message, Colleague colleague) { if (colleague == Colleague1) { Colleague2.Notify(message); } else { Colleague1.Notify(message); } } } /// <summary> /// The 'Colleague' abstract class /// </summary> abstract class Colleague { protected Mediator mediator; // Constructor public Colleague(Mediator mediator) { this.mediator = mediator; } } /// <summary> /// A 'ConcreteColleague' class /// </summary> class ConcreteColleague1 : Colleague { // Constructor public ConcreteColleague1(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message, this); } public void Notify(string message) { Console.WriteLine("Colleague1 gets message: " + message); } } /// <summary> /// A 'ConcreteColleague' class /// </summary> class ConcreteColleague2 : Colleague { // Constructor public ConcreteColleague2(Mediator mediator) : base(mediator) { } public void Send(string message) { mediator.Send(message, this); } public void Notify(string message) { Console.WriteLine("Colleague2 gets message: " + message); } } } Output Colleague2 gets message: How are you? Colleague1 gets message: Fine, thanks
Пример на C++[править | править код]
#include <iostream> #include <string> class Colleague; class Mediator; class ConcreteMediator; class ConcreteColleague1; class ConcreteColleague2; class Mediator { public: virtual void Send(std::string const& message, Colleague *colleague) const = 0; }; class Colleague { protected: Mediator* mediator_; public: explicit Colleague(Mediator *mediator):mediator_(mediator) { } }; class ConcreteColleague1:public Colleague { public: explicit ConcreteColleague1(Mediator* mediator):Colleague(mediator) { } void Send(std::string const& message) { mediator_->Send(message, this); } void Notify(std::string const& message) { std::cout << "Colleague1 gets message '" << message << "'" << std::endl; } }; class ConcreteColleague2:public Colleague { public: explicit ConcreteColleague2(Mediator *mediator):Colleague(mediator) { } void Send(std::string const& message) { mediator_->Send(message, this); } void Notify(std::string const& message) { std::cout << "Colleague2 gets message '" << message << "'" << std::endl; } }; class ConcreteMediator:public Mediator { protected: ConcreteColleague1 *m_Colleague1; ConcreteColleague2 *m_Colleague2; public: void SetColleague1(ConcreteColleague1 *c) { m_Colleague1=c; } void SetColleague2(ConcreteColleague2 *c) { m_Colleague2=c; } virtual void Send(std::string const& message, Colleague *colleague) const { if (colleague==m_Colleague1) { m_Colleague2->Notify(message); } else if (colleague==m_Colleague2) { m_Colleague1->Notify(message); } } }; int main() { ConcreteMediator m; ConcreteColleague1 c1(&m); ConcreteColleague2 c2(&m); m.SetColleague1(&c1); m.SetColleague2(&c2); c1.Send("How are you?"); c2.Send("Fine, thanks"); std::cin.get(); return 0; } Output Colleague2 gets message 'How are you?' Colleague1 gets message 'Fine, thanks'
Пример на Python[править | править код]
from abc import ABCMeta, abstractmethod from weakref import proxy import inspect class Mediator(metaclass=ABCMeta): """ Абстрактный канал общения между коллегами """ @abstractmethod def send(self, message: str) -> None: """ Отправка сообщения между коллегами """ pass class Colleague(metaclass=ABCMeta): """ Абстрактный работник, который не против пообщаться со своими коллегами """ def __init__(self, mediator: Mediator) -> None: """ Constructor. :param mediator: канал общения с коллегами """ self._mediator = proxy(mediator) @abstractmethod def send(self, message: str) -> None: """ Отправка сообщения через канал общения """ pass @abstractmethod def receive(self, message: str) -> None: """ Получения сообщения через канал общения """ pass class SkypeBetweenTwoColleagues(Mediator): """ Канал в скайпе для общения между двумя людьми """ def __init__(self) -> None: """ Constructor. """ self._first = None self._second = None def set_first(self, first: Colleague) -> None: """ Привязывает к каналу первого участника разговора """ self._first = first def set_second(self, second: Colleague) -> None: """ Привязывает к каналу второго участника разговора """ self._second = second def send(self, message: str) -> None: sender = inspect.currentframe().f_back.f_locals['self'] receiver = self._first if sender == self._second else self._second receiver.receive(message) class Bill(Colleague): def send(self, message: str) -> None: self._mediator.send(message) def receive(self, message: str) -> None: print('Билл получил сообщение: {}'.format(message)) class Steve(Colleague): def send(self, message: str) -> None: self._mediator.send(message) def receive(self, message: str) -> None: print('Стив прочитал в скайпе сообщение: {}'.format(message)) if __name__ == '__main__': print('OUTPUT:') skype = SkypeBetweenTwoColleagues() bill = Bill(skype) steve = Steve(skype) skype.set_first(bill) skype.set_second(steve) bill.send('Начинай работать, бездельник!') steve.send('Нет') ''' OUTPUT: Стив прочитал в скайпе сообщение: Начинай работать, бездельник! Билл получил сообщение: Нет '''
Пример на Delphi[править | править код]
program MediatorExample; {$APPTYPE CONSOLE} type IColleague = interface procedure Send(AMessage: string); procedure Notify(AMessage: string); end; TMediator = class procedure Send(AMessage: string; ACollegue: IColleague); virtual; abstract; end; TConcreteMediator = class(TMediator) public FCollegue1: IColleague; FCollegue2: IColleague; procedure Send(AMessage: string; ACollegue: IColleague); override; end; TColleague = class(TInterfacedObject, IColleague) public FMediator: TMediator; constructor Create(AMediator: TMediator); procedure Send(AMessage: string); virtual; abstract; procedure Notify(AMessage: string); virtual; abstract; end; ConcreteColleague1 = class(TColleague) procedure Send(AMessage: string); override; procedure Notify(AMessage: string); override; end; ConcreteColleague2 = class(TColleague) procedure Send(AMessage: string); override; procedure Notify(AMessage: string); override; end; { TConcreteMediator } procedure TConcreteMediator.Send(AMessage: string; ACollegue: IColleague); begin if ACollegue = FCollegue1 then FCollegue2.Notify(AMessage) else FCollegue1.Notify(AMessage); end; { TColleague } constructor TColleague.Create(AMediator: TMediator); begin FMediator := AMediator; end; { ConcreteColleague1 } procedure ConcreteColleague1.Send(AMessage: string); begin FMediator.Send(AMessage, Self); end; procedure ConcreteColleague1.Notify(AMessage: string); begin Writeln('Colleague1 gets message: ' + AMessage); end; { ConcreteColleague2 } procedure ConcreteColleague2.Send(AMessage: string); begin FMediator.Send(AMessage, Self); end; procedure ConcreteColleague2.Notify(AMessage: string); begin Writeln('Colleague2 gets message: ' + AMessage); end; var Mediator: TConcreteMediator; Colleague1: ConcreteColleague1; Colleague2: ConcreteColleague2; begin Mediator := TConcreteMediator.Create; Colleague1 := ConcreteColleague1.Create(Mediator); Colleague2 := ConcreteColleague2.Create(Mediator); Mediator.FCollegue1 := Colleague1; Mediator.FCollegue2 := Colleague2; Colleague1.Send('How are you?'); Colleague2.Send('Fine, thanks'); Readln; end.
Ссылки[править | править код]
- Паттерн Mediator (посредник) — назначение, описание, особенности и реализация на C++.
- Паттерны для масштабируемых JavaScript-приложений. Глава 10. Паттерн «Медиатор» — описание, пример реализации.