Составной шаблон проектирования в Java

Составной шаблон проектирования в Java

1. Вступление

В этом кратком руководстве мы познакомим вас с шаблоном составного проектирования на Java.

Мы собираемся описать структуру и цели ее использования.

2. Структура

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

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

Мы можем разбить шаблон на:

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

  • leaf - реализует поведение по умолчанию базового компонента. Он не содержит ссылки на другие объекты.

  • композитный - имеет листовые элементы. Он реализует методы базового компонента и определяет дочерние операции.

  • клиент - имеет доступ к элементам композиции с помощью объекта базового компонента.

3. Практический пример

Теперь перейдем к реализации. Предположим,we want to build a hierarchical structure of departments in a company.

3.1. Базовый компонент

В качестве объекта-компонента мы определим простой интерфейсDepartment:

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() из базового компонента, где они печатают имена классов для каждого из них.

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

Теперь давайте также рассмотрим составной класс.

3.3. Составной элемент

В качестве составного класса давайте создадим классHeadDepartment:

public class HeadDepartment implements Department {
    private Integer id;
    private String name;

    private List 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);
    }
}

This is a composite class as it holds a collection of Department components, а также методы добавления и удаления элементов из списка.

Составной метод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(). Как и ожидалось,the output contains the class names of each leaf component:

SalesDepartment
FinancialDepartment

5. Заключение

В этой статье мы узнали о шаблоне Composite design. В статье подчеркивается основная структура и демонстрируется использование на практическом примере.

Как обычно, полный код доступен вGithub project.