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

Что это такое

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

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


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

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

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

root.Size() обходит всё дерево без единой проверки типа: папке всё равно, файл ли это на 4 КБ или другая папка, прячущая ещё десяток.

Prompt
Напишите программу на Go с паттерном Composite: интерфейс Item с методом Size, лист File с фиксированным размером и Folder, который содержит Item и рекурсивно складывает их размеры. Постройте небольшое дерево (корневая папка с файлом и папкой docs, содержащей два файла) и выведите размер docs и размер root.
Вывод: программа на Go и захваченный вывод
One interface for leaf and group

Когда его применять

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

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


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

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

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