Структурные шаблоны проектирования
Компоновщик
Применение шаблона "Компоновщик" особенно востребовано, когда в информационной системе реализованы и поддерживаются древовидные структуры объектов. Ярким примером типичной древовидной структуры является пользовательский интерфейс:
- Окно пользовательского интерфейса – контейнер для более простых элементов – панелей, кнопок, полей ввода и т.д.
- Панель тоже является контейнерными объектами вплоть до конечных элементов.
В подобных программных продуктах часто возникают ситуации, когда необходимо обработать группу, структуру или структуры объектов одновременно. Для этого целесообразно определить классы для комплексных и атомарных объектов таким образом, чтобы они реализовывали один и тот же программный интерфейс, но система должна уметь различать составные и атомарные объекты соответственно.
Для решения задачи создания и обработки древовидных элементов необходимо завести общий интерфейс, который будет описывать и элементарные, и составные объекты.
Более того, так как интерфейс описывает и составные объекты, он должен содержать контейнерные методы для добавления, удаления и получения объекта из контейнера. Причем функциональные методы должны быть параметризованы общим интерфейсом. Организация подобного структурного шаблона приводит к возможности автоматического добавления в контейнер не только элементарных объектов, но и других контейнеров.
Достоинствами шаблона "Компоновщик" являются:
- легкость добавления новых примитивных или составных объектов;
- простота структуры программы:
- примитивные и составные объекты обрабатываются одинаковым образом.
К недостаткам следует отнести неудобство реализации запрета на добавление в составной объект компонентов определенных типов.
Мост
Приступая к освоению очередного структурного шаблона, немного порассуждаем о принципах анализа, которые наглядно демонстрируют необходимость применения шаблонов проектирования в целом и шаблона "Мост" в частности.
Анализы общности и изменчивости включают рекомендации по поиску того, что изменяется и что является общим в заданной конкретной ситуации. Решение любой задачи состоит в том, чтобы определить, где возможны изменения (анализ общности), а затем установить, как это изменение может происходит (анализ изменчивости).
- Анализ изменчивости позволяет установить, каким образом и где происходят изменения. Изменчивость имеет смысл только в пределах конкретной общности.
- Анализ общности предусматривает выявление структур, которые вряд ли будут изменяться с течением времени, тогда как анализ изменчивости заключается в обнаружении структур, которые, вероятно, изменятся.
- Анализ изменчивости имеет смысл только в терминах контекста, определенного предварительным анализом общности.
Если рассуждать с точки зрения архитектуры, то анализ общности дает архитектуре долговечность, а анализ изменчивости способствует достижению характеристик гибкости и удобства проектируемого программного продукта.
Общие концепции представляются в системе в виде абстрактных классов.
Вариации, обнаруженные при анализе изменчивости, реализуются посредством создания более конкретных классов–производных от этих абстрактных классов.
Таким образом, если требуется на уровне приложения разделять абстракцию и реализацию так, чтобы и то и другое можно было изменять независимо, применяют паттерн "Мост".
Существующие подходы к решению подобных задач основаны на принципе наследования, что приводит к тому, что реализация жестко привязывается к абстракции и последующая независимая модификация очень сложна.
"Мост"– один из самых трудных для понимания шаблонов проектирования. Это вызвано тем, что он является очень мощным и часто применяется в самых различных ситуациях. Кроме того, он противоречит распространенной практике применения механизма наследования для реализации специальных случаев.
Алгоритм его реализации заключается в помещении абстракции и реализации в отдельные иерархии классов. Этот подход имеет неоспоримое достоинство при выполнении только реализации во время исполнения программы:
- Абстрактный класс определяет свой интерфейс и хранит ссылку на реализуемый объект.
- Реализуемый объект определяет интерфейс для классов реализации:
- Он не обязан точно соответствовать интерфейсу абстрактного класса.
- Оба интерфейса могут быть совершенно различны.
- Реализуемый класс предоставляет только конкретные операции, а абстрактный класс определяет операции более высокого уровня, базирующиеся на этих примитивных.
- При обращении к абстрактному классу он перенаправляет все запросы реализуемому классу.
Применение шаблона "Мост" позволяет получить более устойчивые проектные решения для представления элементов абстракции и реализации, упрощая их возможное последующее изменение.
Решения, использующие механизм наследования "в лоб", приводят к созданию громоздкого программного обеспечения, характеризующегося сильной связанностью и, следовательно, крайне неудобного в сопровождении.
В общем случае, чтобы определить, какой именно структурный шаблон лучше использовать, следует сопоставить его с характеристиками и поведением сущностей в проблемной области.