Padrão de design composto em Java

Padrão de design composto em Java

1. Introdução

Neste tutorial rápido, apresentaremos o padrão de design composto em Java.

Vamos descrever a estrutura e a finalidade de seu uso.

2. A estrutura

O padrão composto destina-se a permitir o tratamento de objetos individuais e composições de objetos, ou "compostos" da mesma maneira.

Ele pode ser visto como uma estrutura em árvore composta de tipos que herdam um tipo de base e pode representar uma única parte ou uma hierarquia inteira de objetos.

Podemos dividir o padrão em:

  • component - é a interface base para todos os objetos na composição. Deve ser uma interface ou uma classe abstrata com os métodos comuns para gerenciar os compostos filhos.

  • leaf - implementa o comportamento padrão do componente base. Ele não contém uma referência aos outros objetos.

  • composto - possui elementos foliares. Ele implementa os métodos do componente base e define as operações relacionadas a filhos.

  • client - tem acesso aos elementos da composição usando o objeto do componente base.

3. Exemplo Prático

Agora, vamos mergulhar na implementação. Vamos suporwe want to build a hierarchical structure of departments in a company.

3.1. O Componente Base

Como um objeto de componente, definiremos uma interfaceDepartment simples:

public interface Department {
    void printDepartmentName();
}

3.2. Leafs

Para os componentes folha, vamos definir classes para os departamentos financeiro e de vendas:

public class FinancialDepartment implements Department {

    private Integer id;
    private String name;

    public void printDepartmentName() {
        System.out.println(getClass().getSimpleName());
    }

    // standard constructor, getters, setters
}

A segunda classe folha,SalesDepartment, é semelhante:

public class SalesDepartment implements Department {

    private Integer id;
    private String name;

    public void printDepartmentName() {
        System.out.println(getClass().getSimpleName());
    }

    // standard constructor, getters, setters
}

Ambas as classes implementam o métodoprintDepartmentName() a partir do componente base, onde imprimem os nomes das classes para cada uma delas.

Além disso, como são classes folha, não contêm outros objetosDepartment.

A seguir, vamos ver uma classe composta também.

3.3. O Elemento Composto

Como uma classe composta, vamos criar uma classeHeadDepartment:

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, bem como métodos para adicionar e remover elementos da lista.

O métodoprintDepartmentName() composto é implementado iterando sobre a lista de elementos folha e invocando o método apropriado para cada um.

4. Teste

Para fins de teste, vamos dar uma olhada em uma classeCompositeDemo:

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();
    }
}

Primeiro, criamos duas instâncias para os departamentos financeiro e de vendas. Depois, instanciamos o departamento principal e adicionamos nele as instâncias criadas anteriormente.

Finalmente, podemos testar o método de composiçãoprintDepartmentName(). Como esperamos,the output contains the class names of each leaf component:

SalesDepartment
FinancialDepartment

5. Conclusão

Neste artigo, aprendemos sobre o padrão de design composto. O artigo destaca a estrutura principal e demonstra o uso através do exemplo prático.

Como de costume, o código completo está disponível emGithub project.