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

Паттерн "Компоновщик" (Composite) в Java — дерево отдела и единый интерфейс

Разработчику Архитектору

Краткий обзор — в структурных паттернах. Здесь — практический Composite на Java для иерархической оргструктуры.

Загрузка редактора схем…

Задача паттерна

Composite позволяет работать с отдельным объектом и группой объектов одинаково.

Типичный кейс — дерево:

  • лист — единичный элемент;
  • композит — узел с дочерними элементами;
  • клиент использует общий интерфейс и не ветвится по типам.

Пример — структура отдела

import java.util.ArrayList;
import java.util.List;

interface OrganizationUnit {
String getName();
long getSalary();
}

class Employee implements OrganizationUnit {
private final String name;
private final long salary;

Employee(String name, long salary) {
this.name = name;
this.salary = salary;
}

@Override
public String getName() {
return name;
}

@Override
public long getSalary() {
return salary;
}
}

class Department implements OrganizationUnit {
private final String name;
private final List<OrganizationUnit> units = new ArrayList<>();

Department(String name) {
this.name = name;
}

void add(OrganizationUnit unit) {
units.add(unit);
}

@Override
public String getName() {
return name;
}

@Override
public long getSalary() {
return units.stream().mapToLong(OrganizationUnit::getSalary).sum();
}
}
Department dev = new Department("Разработка");
dev.add(new Employee("Анна", 200_000));
dev.add(new Employee("Борис", 180_000));

Department company = new Department("Компания");
company.add(dev);
company.add(new Employee("CEO Иван", 500_000));

System.out.println(company.getSalary()); // 880000

Клиент вызывает getSalary() одинаково и для Employee, и для Department.


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

СценарийComposite
Файловая система, UI-дерево, меню, оргструктураЕдиный интерфейс для листьев и узлов
Нужна рекурсивная агрегация метрикКомпозит делегирует вычисление детям
Клиентский код должен быть простымУбираются instanceof-ветвления

Composite и Iterator

Composite описывает структуру, Iterator — обход.

Их часто применяют вместе: структура хранится как дерево Composite, обход выполняется итератором (DFS/BFS). См. Итератор в Java.


Риски

Трудно жестко ограничить допустимые типы дочерних элементов в общем интерфейсе. Проверки состава часто уходят в runtime-валидацию.


См. также

См. также

Другие статьи этого же раздела в боковом меню (как на странице "О разделе").