Определение

Структурные паттерны проектирования (Structural Patterns) — это шаблоны, которые помогают организовать классы и объекты в более крупные структуры, сохраняя при этом гибкость и эффективность системы. Они решают задачи, связанные с композицией объектов и классов, упрощая взаимодействие между ними и делая систему более модульной.

Рассмотрим подробнее каждый из порождающих паттернов:

Адаптер

Adapter

Назначение: Позволяет объектам с несовместимыми интерфейсами работать вместе. Преобразует интерфейс одного класса в интерфейс, ожидаемый клиентом.

Когда использовать: Когда нужно интегрировать старый код или сторонние библиотеки с новым кодом, или когда интерфейсы классов не совместимы.

Пример: Адаптер для работы с разными типами розеток (европейская и американская). Адаптер позволяет использовать устройство с одной вилкой в розетке другого типа.

Преимущества:

  • Упрощает интеграцию несовместимых интерфейсов.
  • Позволяет повторно использовать существующий код.
  • Делает систему более гибкой.

Мост

Bridge

Назначение: Разделяет абстракцию и реализацию так, чтобы они могли изменяться независимо. Позволяет избежать наследования и делает систему более гибкой.

Когда использовать: Когда нужно разделить абстракцию (что делает объект) и реализацию (как он это делает), чтобы они могли изменяться независимо.

Пример: Управление разными типами устройств (например, телевизорами и пультами). Абстракция — это пульт, а реализация — это конкретное устройство.

Преимущества:

  • Упрощает добавление новых абстракций и реализаций.
  • Уменьшает количество классов в системе.
  • Делает систему более расширяемой.

Компоновщик

Composite

Назначение: Позволяет сгруппировать объекты в древовидные структуры для работы с ними как с единым объектом. Объединяет объекты в иерархии "часть-целое".

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

Пример: Файловая система, где папки могут содержать файлы и другие папки. Клиентский код работает с папками и файлами одинаково.

Преимущества:

  • Упрощает работу с древовидными структурами.
  • Позволяет добавлять новые типы компонентов.
  • Уменьшает сложность кода.

Декоратор

Decorator

Назначение: Динамически добавляет объекту новые обязанности, является гибкой альтернативой наследованию. Позволяет расширять функциональность объектов без изменения их структуры.

Когда использовать: Когда нужно добавлять новые функции объектам во время выполнения, или когда наследование не подходит из-за большого количества комбинаций.

Пример: Добавление функциональности к текстовому редактору (например, добавление форматирования, проверки орфографии).

Преимущества:

  • Позволяет добавлять новые функции без изменения существующего кода.
  • Упрощает комбинирование функций.
  • Избегает "взрыва подклассов".

Фасад

Facade

Назначение: Предоставляет простой интерфейс к сложной системе классов. Скрывает сложность системы, предоставляя клиенту удобный интерфейс.

Когда использовать: Когда нужно упростить взаимодействие с сложной системой или библиотекой.

Пример: Упрощение работы с API сложной библиотеки (например, для работы с графикой или базами данных).

Преимущества:

  • Упрощает использование сложных систем.
  • Изолирует клиентский код от подсистем.
  • Уменьшает зависимости между компонентами.

Приспособленец

Flyweight

Назначение: Экономит память, разделяя состояние между множеством объектов. Используется для работы с большим количеством мелких объектов.

Когда использовать: Когда в системе используется большое количество объектов, которые могут быть разделены на внутреннее (неизменяемое) и внешнее (изменяемое) состояние.

Пример: Работа с текстовым редактором, где каждый символ может быть представлен как объект. Внутреннее состояние — это шрифт и размер, а внешнее — позиция символа.

Преимущества:

  • Экономит память.
  • Уменьшает количество создаваемых объектов.
  • Упрощает работу с большими наборами данных

Заместитель

Proxy

Назначение: Позволяет подставлять вместо реальных объектов специальные объекты-заменители. Заместитель контролирует доступ к реальному объекту.

Когда использовать: Когда нужно контролировать доступ к объекту (например, для ленивой инициализации, кэширования или контроля прав доступа).

Пример: Ленивая загрузка изображений на веб-странице. Заместитель загружает изображение только тогда, когда оно становится видимым.

Преимущества:

  • Управляет доступом к объекту.
  • Позволяет добавлять дополнительную логику (например, кэширование).
  • Упрощает работу с ресурсоемкими объектами.

Общие преимущества порождающих паттернов

Гибкость: Позволяют изменять структуру системы без изменения её поведения.

Изоляция: Упрощают взаимодействие между компонентами системы.

Повторное использование: Способствуют повторному использованию кода.

Управление сложностью: Упрощают работу с сложными системами, разбивая их на более мелкие части.

Пример использования порождающих паттернов

Представьте, что вы разрабатываете графический редактор:

  • Адаптер может использоваться для интеграции сторонних библиотек для работы с изображениями.
  • Мост разделяет абстракцию (графические примитивы) и реализацию (отрисовка на экране или в файл).
  • Компоновщик позволяет работать с группами объектов (например, слоями) как с единым объектом.
  • Декоратор добавляет новые функции к объектам (например, рамки или тени).
  • Фасад упрощает работу с сложным API графической библиотеки.
  • Приспособленец экономит память, разделяя общие данные между множеством объектов (например, текстуры).
  • Заместитель управляет доступом к ресурсоемким объектам (например, изображениям высокого разрешения).

Таким образом, структурные паттерны помогают создавать более гибкие, модульные и эффективные системы.