1. Введение
В этом кратком руководстве мы познакомим вас с составным шаблоном проектирования в Java.
Мы собираемся описать структуру и цель ее использования.
2. Структура
Комбинированный шаблон предназначен для того, чтобы можно было одинаково обрабатывать отдельные объекты и композиции объектов или «композиты».
Его можно рассматривать как древовидную структуру, состоящую из типов, наследующих базовый тип, и он может представлять собой одну часть или целую иерархию объектов.
Мы можем разбить шаблон на:
- компонент — это базовый интерфейс для всех объектов в композиции. Это должен быть либо интерфейс, либо абстрактный класс с общими методами для управления дочерними композитами.
- leaf — реализует поведение базового компонента по умолчанию. Он не содержит ссылки на другие объекты.
- составной – имеет листовые элементы. Он реализует методы базового компонента и определяет дочерние операции.
- клиент — имеет доступ к элементам композиции, используя объект базового компонента.
3. Практический пример
Теперь давайте погрузимся в реализацию. Предположим, мы хотим построить иерархическую структуру отделов в компании.
3.1. Базовый компонент
В качестве объекта-компонента мы определим простой интерфейс отдела :
public interface Department {
void printDepartmentName();
}
3.2. Листья
Для конечных компонентов определим классы для финансового отдела и отдела продаж:
public class FinancialDepartment implements Department {
private Integer id;
private String name;
public void printDepartmentName() {
System.out.println(getClass().getSimpleName());
}
// standard constructor, getters, setters
}
Второй конечный класс, SalesDepartment,
аналогичен:
public class SalesDepartment implements Department {
private Integer id;
private String name;
public void printDepartmentName() {
System.out.println(getClass().getSimpleName());
}
// standard constructor, getters, setters
}
Оба класса реализуют метод printDepartmentName()
из базового компонента, где они печатают имена классов для каждого из них.
Кроме того, поскольку они являются конечными классами, они не содержат других объектов отдела .
Далее, давайте также рассмотрим составной класс.
3.3. Составной элемент
В качестве составного класса создадим класс HeadDepartment
:
public class HeadDepartment implements Department {
private Integer id;
private String name;
private List<Department> childDepartments;
public HeadDepartment(Integer id, String name) {
this.id = id;
this.name = name;
this.childDepartments = new ArrayList<>();
}
public void printDepartmentName() {
childDepartments.forEach(Department::printDepartmentName);
}
public void addDepartment(Department department) {
childDepartments.add(department);
}
public void removeDepartment(Department department) {
childDepartments.remove(department);
}
}
Это составной класс, так как он содержит коллекцию компонентов отдела
, а также методы добавления и удаления элементов из списка.
Составной метод printDepartmentName()
реализуется путем перебора списка конечных элементов и вызова соответствующего метода для каждого из них.
4. Тестирование
В целях тестирования давайте взглянем на класс CompositeDemo :
public class CompositeDemo {
public static void main(String args[]) {
Department salesDepartment = new SalesDepartment(
1, "Sales department");
Department financialDepartment = new FinancialDepartment(
2, "Financial department");
HeadDepartment headDepartment = new HeadDepartment(
3, "Head department");
headDepartment.addDepartment(salesDepartment);
headDepartment.addDepartment(financialDepartment);
headDepartment.printDepartmentName();
}
}
Во-первых, мы создаем два экземпляра для финансового отдела и отдела продаж. После этого мы создаем головной отдел и добавляем к нему ранее созданные экземпляры.
Наконец, мы можем протестировать метод композиции printDepartmentName()
. Как мы и ожидали, вывод содержит имена классов каждого листового компонента :
SalesDepartment
FinancialDepartment
5. Вывод
В этой статье мы узнали о шаблоне проектирования Composite. В описании подчеркивается основная структура и демонстрируется использование на практическом примере.
Как обычно, полный код доступен в проекте Github .