Перейти к основному содержимому

Что это такое

Паттерн Composite работает с отдельными объектами и группами объектов через один и тот же интерфейс. У файла есть размер; у папки, полной файлов (и папок), тоже есть размер — поэтому оба реализуют size(), и код, который суммирует размеры, никогда не спрашивает, что именно он держит.

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


Пример: файлы и папки

У интерфейса Item один метод. FileItem отвечает своим собственным размером; Folder спрашивает всё, что внутри, и складывает — рекурсия получается сама собой.

Один интерфейс для листа и группы

root.size() обходит всё дерево без единой проверки типа: папке всё равно, является ли элемент файлом на 4 КБ или другой папкой, которая прячет ещё десять. Папка docs отвечает 10, а root отвечает 12 — свой файл на 2 КБ плюс всё, что внутри docs.

Prompt
Напишите программу на TypeScript, демонстрирующую паттерн Composite: интерфейс Item с методом size, лист FileItem, хранящий фиксированный размер в КБ, и класс Folder, который держит Items и рекурсивно суммирует их размеры. Постройте корневую папку, содержащую файл на 2 КБ и папку docs с файлами на 4 КБ и 6 КБ, затем выведите размер docs и размер root.
Вывод: программа на TypeScript и захваченный вывод
One interface for leaf and group

Когда использовать

Используйте для древовидных данных, где группы и отдельные элементы отвечают на одни и те же вопросы — файловые системы, меню с подменю, разметка интерфейса, организационные структуры.

Не используйте для плоских списков. Массиву с циклом никакой паттерн не нужен.


Плюсы и минусы

Плюсы: клиентский код остаётся простым и плоским; деревья любой глубины получаются бесплатно; новые классы листьев или групп подключаются к тому же интерфейсу.

Минусы: общий интерфейс может навязать листьям неудобные методы (что такое «добавить потомка» у файла?); слишком общие композиты трудно ограничить.