- •А.А. Волосевич
- •3. Шаблоны и архитектура программ
- •3.1. Модульное тестирование
- •3.2. Шаблоны проектирования
- •3.3. Структурные шаблоны: Декоратор, Заместитель, мост Декоратор (Decorator)
- •Заместитель (Proxy)
- •Мост (Bridge)
- •3.4. Структурные шаблоны: компоновщик и приспособленец Компоновщик (Composite)
- •Приспособленец (Flyweight)
- •3.5. Структурные шаблоны: адаптер и фасад Адаптер (Adapter)
- •Фасад (Façade)
- •3.6. Порождающие шаблоны: прототип, фабричный метод, одиночка Прототип (Prototype)
- •Фабричный метод (Factory method)
- •Одиночка (Singleton)
- •3.7. Порождающие шаблоны: абстрактная фабрика и строитель Абстрактная фабрика (Abstract factory)
- •Строитель (Builder)
- •3.8. Шаблоны поведения: стратегия, состояние, шаблонный метод Стратегия (Strategy)
- •Состояние (State)
- •Шаблонный метод (Template method)
- •3.9. Шаблоны поведения: цепочка обязанностей и команда Цепочка обязанностей (Chain of responsibility)
- •Команда (Command)
- •3.10. Шаблоны поведения: итератор, посредник, наблюдатель Итератор (Iterator)
- •Посредник (Mediator)
- •Наблюдатель (Observer)
- •3.11. Шаблоны поведения: посетитель, интерпретатор, хранитель Посетитель (Visitor)
- •Интерпретатор (Interpreter)
- •Хранитель (Memento)
- •3.12. Некоторые неклассические шаблоны проектирования
- •Неизменный объект (Immutable object)
- •Пул объектов (Object pool)
- •Отложенная инициализация (Lazy initialization)
- •Нулевой объект (Null object)
- •3.13. Антипаттерны
- •3.14. Архитектура прогРаммного Обеспечения
- •«Клиент-сервер»
- •Архитектура, основанная на использовании компонентов
- •Многоуровневая архитектура
- •Шина сообщений
- •Выделенное представление
- •Объектно-ориентированная архитектура
- •Архитектура, ориентированная на сервисы
Посредник (Mediator)
Шаблон Посредник служит для обеспечения коммуникации между объектами. Этот шаблон также инкапсулирует протокол, которому должна удовлетворять процедура коммуникации.
Приведём следующую иллюстрацию применимости шаблона Посредник. Пусть имеется электронная форма для ввода анкетных данных. Эта форма содержит различные элементы управления – объекты определенных классов. Сценарий работы с формой предполагает изменение состояния одних объектов в зависимости от состояния других. Например, в зависимости от значения поля «Пол» меняется доступность переключателя «Служили ли в армии?». Тривиальное решение предполагает, что каждый из объектов, соответствующих определённому элементу формы, при изменении собственных данных будет изменять состояние связанных с ним объектов. Это приводит к росту зависимостей между объектами и увеличению сложности системы. Использование шаблона Посредник подразумевает выделение отдельного объекта, «дирижирующего» поведением элементов управления в зависимости от текущего состояния.
Рис. 21. Дизайн шаблона Посредник.
Дизайн шаблона посредник предполагает наличие двух выделенных классов, использующих сообщения для взаимного обмена информацией: Colleague (коллега) и Mediator (посредник). Объект Colleague регистрирует объект Mediator и сохраняет его в своём внутреннем поле. При регистрации посреднику предоставляется функция обратного вызова Receive(). В свою очередь, посредник поддерживает список зарегистрировавших его объектов. Как только один из объектов Colleague вызывает свой метод Send(), посредник вызывает у остальных зарегистрированных объектов метод Receive(). При практической реализации шаблона Посредник в .NET Framework список зарегистрированных объектов можно поддерживать в виде словаря, а можно использовать для рассылки сообщений возможности групповых делегатов.
Далее представлен код, демонстрирующий использование шаблона.
using System;
using System.Collections.Generic;
public class Mediator
{
public delegate void Callback(string message, string from);
private readonly HashSet<Colleague> colleagues =
new HashSet<Colleague>();
public void SignOn(Colleague colleague)
{
colleagues.Add(colleague);
}
// Посылка сообщения всем коллегам
public void Send(string message, string from)
{
foreach (var colleague in colleagues)
{
colleague.Receive(message, from);
}
}
}
public class Colleague
{
private readonly Mediator mediator;
protected string name;
public Colleague(Mediator mediator, string name)
{
this.mediator = mediator;
this.name = name;
mediator.SignOn(this);
}
public virtual void Receive(string message, string from)
{
Console.WriteLine("{0} received from {1}: {2}",
name, from, message);
}
public void Send(string message)
{
Console.WriteLine("Send (from {0}): {1}", name, message);
mediator.Send(message, name);
}
}
public class AnotherColleague : Colleague
{
public AnotherColleague(Mediator mediator, string name)
: base(mediator, name) { }
// Собственные сообщения игнорируем
public override void Receive(string message, string from)
{
if (!String.Equals(from, name))
{
Console.WriteLine("{0} received from {1}: {2}",
name, from, message);
}
}
}
public class MediatorExample
{
private static void Main()
{
var m = new Mediator();
var john = new Colleague(m, "John");
var lucy = new Colleague(m, "Lucy");
var david = new AnotherColleague(m, "David");
john.Send("Meeting on Tuesday, please all ack");
david.Send("Ack");
john.Send("Still awaiting some Acks");
lucy.Send("Ack");
john.Send("Thanks all");
}
}