Skip to content

Latest commit

 

History

History
88 lines (55 loc) · 8.94 KB

Composite.md

File metadata and controls

88 lines (55 loc) · 8.94 KB

Компоновщик

UML

Объединяет объекты в древовидную структуру для представления иерархии от частного к целому. Компоновщик позволяет клиентам обращаться к отдельным объектам и к группам объектов одинаково.

Лист - это простой элемент дерева, не имеющий ответвлений.

Контейнер (или «композит» или узел) - это составной элемент дерева. Он содержит набор дочерних компонентов, но ничего не знает об их типах. Это могут быть как простые компоненты-листья, так и другие компоненты-контейнеры. Но это не является проблемой, так как все дочерние элементы следуют общему интерфейсу.

Применимость

  • Когда вам нужно представить древовидную структуру объектов.

    • Паттерн Компоновщик предлагает хранить в составных объектах ссылки на другие простые или составные объекты. Те, в свою очередь, тоже могут хранить свои вложенные объекты и так далее. В итоге вы можете строить сложную древовидную структуру данных, используя всего две основные разновидности объектов.
  • Когда клиенты должны единообразно трактовать простые и составные объекты.

    • Благодаря тому, что простые и составные объекты реализуют общий интерфейс, клиенту безразлично с каким именно объектом ему предстоит работать.

Шаги реализации

  1. Убедитесь, что вашу бизнес-логику можно представить как древовидную структуру. Попытайтесь разбить её на простые элементы и контейнеры. Помните, что контейнеры могут содержать как простые элементы, так и другие контейнеры.

  2. Создайте общий интерфейс компонентов, который объединит операции контейнеров и простых элементов дерева. Интерфейс будет удачным, если вы сможете взаимозаменять простые и составные компоненты без потери смысла.

  3. Создайте класс компонентов-листьев, не имеющих дальнейших ответвлений. Имейте в виду, что программа может содержать несколько видов таких классов.

  4. Создайте класс компонентов-контейнеров, и добавьте в него массив для хранения ссылок на вложенные компоненты. Этот массив должен быть способен содержать как простые, так и составные компоненты, поэтому убедитесь, что он объявлен с типом интерфейса компонентов.

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

  5. Добавьте операции добавления и удаления дочерних элементов в класс контейнеров.

    (Ex) Имейте в виду, что методы добавления/удаления дочерних элементов можно поместить и в интерфейс компонентов. Да, это нарушит принцип разделения интерфейса, так как реализации методов будут пустыми в компонентах-листьях. Но зато все компоненты дерева станут действительно одинаковыми для клиента.

Преимущества и недостатки

+ -
Упрощает архитектуру клиента при работе со сложным деревом компонентов. Создаёт слишком общий дизайн классов.
Облегчает добавление новых видов компонентов.

Отношения с другими паттернами

  • Строитель позволяет пошагово сооружать дерево Компоновщика.

  • Цепочку обязанностей часто используют вместе с Компоновщиком. В этом случае, запрос передаётся от дочерних компонентов к их родителям.

  • (Ex)Вы можете обходить дерево Компоновщика, используя Итератор.

  • Вы можете выполнить какое-то действие над всем деревом Компоновщика при помощи Посетителя.

  • Компоновщик часто совмещают с Легковесом, чтобы реализовать общие ветки дерева и сэкономить при этом память.

  • Компоновщик и Декоратор имеют похожие структуры классов из-за того, что оба построены на рекурсивной вложенности. Она позволяет связать в одну структуру бесконечное количество объектов.

    Декоратор оборачивает только один объект, а узел Компоновщика может иметь много детей. Декоратор добавляет вложенному объекту новую функциональность, а Компоновщик не добавляет ничего нового, но «суммирует» результаты всех своих детей.

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

  • Архитектура, построенная на Компоновщиках и Декораторах, часто может быть улучшена за счёт внедрения Прототипа. Он позволяет клонировать сложные структуры объектов, а не собирать их заново.