- •А.А. Волосевич
- •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. Архитектура прогРаммного Обеспечения
- •«Клиент-сервер»
- •Архитектура, основанная на использовании компонентов
- •Многоуровневая архитектура
- •Шина сообщений
- •Выделенное представление
- •Объектно-ориентированная архитектура
- •Архитектура, ориентированная на сервисы
Мост (Bridge)
Шаблон Мост используется в тех случаях, когда имеется отдельная иерархия абстрактных классов и интерфейсов и соответствующая иерархия реализаций. Мост соединяет абстракции и реализации в виде независимых динамических классов.
В качестве иллюстрации применения шаблона Мост рассмотрим следующий пример. Пусть имеется иерархия классов, описывающая некие абстрактные измерительные датчики. Также имеются отдельные реализации этой иерархии от фирм A и B. В случае использование шаблона Мост клиент будет работать с абстрактной иерархией, к которой динамически подключаются необходимые реализации. Выбор конкретной реализации может выполняться по-разному, например, на основе данных в файле конфигурации.
Рис. 5 демонстрирует упрощенную диаграмму дизайна шаблона Мост. На диаграмме показан только один абстрактный тип. Этот тип агрегирует некий конкретный объект-мост, которому делегируется выполнение требуемых операций.
Рис. 5. UML-диаграмма шаблона Мост.
При реализации шаблона инстанциирование конкретного моста обычно происходит в конструкторе. Далее приведён пример кода, приблизительно соответствующий описанной выше иллюстрации применения шаблона Мост.
public class Sensor
{
private readonly Bridge bridge;
public Sensor(Bridge bridge)
{
this.bridge = bridge;
}
public double GetValue()
{
return bridge.GetSensorValue();
}
}
public interface Bridge
{
double GetSensorValue();
}
public class ImplementationA : Bridge
{
public double GetSensorValue()
{
System.Console.WriteLine("Implementation A");
return -1;
}
}
public class ImplementationB : Bridge
{
public double GetSensorValue()
{
System.Console.WriteLine("Implementation B");
return 0;
}
}
public class BridgeExample
{
private static void Main()
{
var sensor = new Sensor(new ImplementationA());
sensor.GetValue();
}
}
3.4. Структурные шаблоны: компоновщик и приспособленец Компоновщик (Composite)
Компоновщик – один из простейших структурных шаблонов. Его задача – агрегировать объекты, обладающие общим интерфейсом, и обеспечить выполнение операций этого интерфейса над всеми агрегируемыми объектами.
Простейшей иллюстрацией применения шаблона Компоновщик может служить средство для просмотра изображений, которое позволяет изменить некие характеристики как одного изображения, так и группы совместно отображаемых объектов.
Дизайн шаблона Компоновщика показан на рис. 6. То, что и компоновщик, и отдельный объект реализуют один и тот же интерфейс, удобно с точки зрения клиента, который не видит разницы между ними в плане функциональности. Обычно компоновщика снабжают методами добавления, удаления, редактирования и поиска отдельных агрегируемых компонент.
Рис. 6. Дизайн шаблона Компоновщик.
Рассмотрим пример реализации шаблона Компоновщик. Код примера позволяет организовывать вложенность компонентов произвольной глубины, а также реализует типичные операции с компонентами.
using System;
using System.Collections.Generic;
public interface IComponent<T>
{
T Item { get; set; }
void Add(IComponent<T> c);
IComponent<T> Remove(T s);
IComponent<T> Find(T s);
}
// Отдельный компонент
public class Component<T> : IComponent<T>
{
public T Item { get; set; }
public Component(T item)
{
Item = item;
}
public void Add(IComponent<T> c)
{
Console.WriteLine("Cannot add to an item");
}
public IComponent<T> Remove(T s)
{
Console.WriteLine("Cannot remove directly");
return this;
}
public IComponent<T> Find(T s)
{
return s.Equals(Item) ? this : null;
}
}
// Компоновщик
public class Composite<T> : IComponent<T>
{
private readonly List<IComponent<T>> list;
public T Item { get; set; }
public Composite(T item)
{
Item = item;
list = new List<IComponent<T>>();
}
public void Add(IComponent<T> c)
{
list.Add(c);
}
public IComponent<T> Remove(T s)
{
var p = Find(s);
if (p != null)
{
list.Remove(p);
}
return this;
}
public IComponent<T> Find(T s)
{
if (Item.Equals(s))
{
return this;
}
IComponent<T> found = null;
foreach (var c in list)
{
found = c.Find(s);
if (found != null)
{
break;
}
}
return found;
}
}