Padrão de Projeto Composite: O que é, prós e contras e como implementar?
Se você atua com projetos de software e já teve a necessidade de tratar objetos individuais e coleções de objetos de forma uniforme, o padrão de projeto Composite vai te ajudar.
Descubra a seguir como o padrão Composite auxilia na criação de interfaces de usuário mais intuitivas e no processamento de árvores de objetos de forma eficiente.
Neste artigo, convidamos você a explorar os benefícios desse padrão, que simplifica estruturas hierárquicas e oferece maior flexibilidade na manipulação de elementos.
Confira abaixo o que é o Composite, quais suas vantagens e desvantagens e veja um exemplo prático da sua implementação.
O que é o Composite?
O Composite é um padrão de projeto estrutural que permite tratar de maneira uniforme os objetos individuais e composições de objetos, formando uma estrutura hierárquica.
Ele é o quarto padrão desta categoria apresentado pela "Gang of Four" (GoF).
Como os próprios autores colocam, a intenção oficial deste padrão é “compor objetos em estruturas de árvore para representar hierarquias partes-todo".
Com o Composite, um objeto individual e um grupo de objetos são tratados da mesma maneira, pois ambos implementam uma interface comum.
Como funciona o padrão de projeto Composite?
Dentro do padrão Composite, encontramos uma classe abstrata conhecida como "Componente", que estabelece uma interface compartilhada para objetos individuais e grupos de objetos.
Os objetos individuais são representados por uma classe concreta que implementa o Componente, enquanto os grupos de objetos são representados por uma classe composta que também implementa o Componente.
A estrutura hierárquica é criada através da composição, na qual um grupo de objetos pode incluir outros objetos individuais ou grupos de objetos. Essa estrutura permite a realização de interações recursivas, e dessa forma possibilita a aplicação de operações a todos os objetos na hierarquia.
O padrão Composite é ideal para quando há a necessidade de tratar objetos individuais e coleções de objetos de forma homogênea, simplificando o código e conferindo maior flexibilidade.
Seu uso é comum em interfaces de usuário, processamento de árvores e outras estruturas hierárquicas.
Como é a implementação do Composite?
Para entender melhor a implementação do Composite, vamos analisar o exemplo a seguir:
Em um supermercado, você possui duas formas de comprar um refrigerante:
- É possível comprar a unidade
- Ou comprar um fardo com 12 unidades
Aqui, nós temos um Composite: a noção de que o fardo (estrutura) se comporta como um produto, e que ele pode dizer seu preço delegando o seu valor, somando assim os custos das unidades filhas e utilizando como seu próprio.
Claro, o cenário acima só faz sentido se o fardo não possuir um valor fixo, e sim que seu valor se resume no total de unidades que há dentro do mesmo.
Vejamos um código do cenário descrito (no caso, utilizando Java para exemplificar):
No exemplo acima, definimos uma interface Produto, que será implementada tanto pela unidade de “refrigerante”, quanto pelo fardo. O método em comum que será implementado por eles, no nosso caso, é o getValor().
O refrigerante, por sua vez, possui o valor e um nome. A implementação do getValor(), por ser uma única unidade, apenas retorna o seu próprio valor.
Acima temos o fardo de refrigerantes, atuando como Composite, seu “valor” é delegado para as unidades que há dentro dele.
Ou seja, se houver 5 unidades de refrigerante, cada uma com um valor “5”, o valor do fardo será de 25.
O interessante neste design pattern é que a complexidade desse tipo de estrutura não acaba por aí.
Como a classe FardoDeRefrigerante possui uma lista dentro de si do tipo Produto, ela é capaz de suportar até mesmo outros fardos dentro de si mesma.
Exemplo da Estrutura de um Composite
Apesar de o “fardo de refrigerante” não ser o melhor exemplo nesse caso, podemos imaginar uma caixa dentro de outra caixa, e cada uma delas com produtos de diferentes valores dentro de si, as caixas internas totalizaram o valor dos produtos internos, e a caixa externa totalizaria o valor das caixas internas, parecendo muito com a estrutura abaixo:
Exemplo de como a estrutura de um composite pode ficar. Fonte: “Padrões de Projetos: Soluções Reutilizáveis de Software Orientados a Objetos”
Normalmente utiliza-se o padrão de projeto Composite, por exemplo, para rodar uma bateria de validações em cima de um objeto.
Enquanto o Decorator serve para estender funcionalidades dentro de uma classe já existente, sem alterar a classe original e preservando os princípios SOLID.
A forma de implementação pode variar bastante dependendo de como que você utiliza, mas o importante é conhecer o padrão e saber quando encaixá-lo no seu sistema.
Não siga à risca os diagramas propostos pela GoF, ou os exemplos citados, adeque-os de acordo com suas necessidades e situações.
Quando usar o padrão de projeto Composite?
Aplica-se o padrão de projeto Composite nas situações em que há uma estrutura hierárquica de objetos e quando se deseja tratar objetos individuais e grupos de objetos de forma uniforme, simplificando o código e fornecendo maior flexibilidade.
Aqui estão algumas situações de exemplo do uso do padrão Composite:
- Estruturas Hierárquicas:
O padrão Composite é ideal para lidar com estruturas hierárquicas, como árvores ou grafos, onde os nós podem ser objetos individuais ou grupos de objetos.
- Modelagem de Interface de Usuário:
É comum utilizar o padrão Composite na construção de interfaces de usuário, especialmente quando há elementos que podem conter outros elementos, como menus, botões e painéis.
- Processamento de Documentos:
O Composite pode ser útil para tratar elementos como documentos com seções, parágrafos, listas, etc, de forma uniforme.
- Manipulação de Gráficos:
Se você precisa lidar com elementos gráficos, como formas, linhas e grupos de formas, o Composite permite tratá-los de maneira uniforme e facilita a aplicação de operações a todos os elementos.
- Implementação de Estruturas de Dados:
Também é possível aplicar o Composite na implementação de estruturas de dados como arrays, listas e matrizes, em que tratam-se os elementos individuais e os grupos de elementos de forma semelhante.
Quais os prós e contras de usar o Composite?
Confira os principais prós e contras do Composite:
Prós | Contras |
Simplifica a estrutura hierárquica | Pode ter impacto na eficiência em estruturas muito grandes |
Oferece flexibilidade na manipulação de objetos e operações recursivas | Pode exigir maior esforço de design e implementação inicial |
Promove reuso do código | Requer uma interface comum bem definida |
No entanto, é importante lembrar que os prós e contras do Composite podem variar dependendo do contexto e dos requisitos específicos do projeto.
Portanto, é essencial considerar cuidadosamente esses aspectos antes de decidir utilizar o design pattern Composite.
E você já sabia como implementar o Composite? Aproveite e confira outros conteúdos de tecnologia no Tech Writers.