Composite

Este texto foi atualizado e doado ao projeto Code Design World.
Leia a versão mais atualizada.

Composite

Composite(Objecto Composto) é um padrão de projeto que permite que um objeto seja constituido de outros objetos semelhantes a ele formando uma hierarquia.[1].

Utilizando o padrão Composite é simples criar uma hierarquia de objetos semelhantes. Semelhantes, significa aqui, objetos que implementam uma interface comum. O padrão simplifica o tratamentos de cada elemento da hierarquia ao tratar a todos como implementações da mesma interface.

O problema

Você quer construir um objeto que seja construido de outros objetos tal que, um ou mais objetos desses podem ser do mesmo tipo do objeto construido. O objeto é construido por objetos que contém uma coleção de outros objetos. Os quais contêm uma coleção de outros objetos, e assim sucessivamente. Contudo esses objetos não são quaisquer, eles compatilham uma interface comum. Por exemplo, um objeto do tipo Forma. Existem várias formas, mas todas elas podem ser construidas pela composição de outras formas. Um ou mais formas são primitivas, ou seja, não são construidas a partir de nenhuma forma, outras serão. O exemplo mais simples é a forma Linha que representa uma semi-reta. Um Triangulo é composto por três Linha. Um quadrado por quatro ,e etc… Um circulo não é representável por um conjunto finito de linhas, logo precisamos de uma forma primitiva Circulo.
Como construir os objetos do tipo Forma para que eles obdeçam a esta hirarquia é o que o padrão Composite resolve.

A solução

O padrão propõe que se construa uma interface ou classe abstrata que representa o tipo de objeto na hierarquia. Para que o padrão possa ser aplicado tem que existir esta interface ou classe (vou apenas usar o termo interface para simplificar).

Objetos que implementam esta interface podem ser de dois tipos: primitivos e compostos.
Os objetos primitivos são aqueles que não se podem construir com base em outros objetos do mesmo tipo. Os compostos, são, claro, aqueles que se constroem com base num conjunto de outros objetos do mesmo tipo.

composite.png
Ilustração 1: Diagrama UML representativo do padrão Composite

Quando usar

Este padrão pode ser usado sempre que desejarmos construir objetos pela composição recursiva de objetos do mesmo tipo e/ou queiramos construir uma hierarquia de objetos do mesmo tipo. Este é o padrão por detrás da estrutura de árvore , muito utilizada em computação. A estrutura de arvore tem como primitivas as folhas. Os ramos são os objetos compostos. A árvore é uma composição de ramos, por sua vez compostos de ramos menores, por sua vez compostos de ramos menores e folhas.

Sempre que estiver perante uma estrutura deste tipo, ou semelhante. Poderá usar o padrão Composite.

Implementação

Não existe uma implementação especifica do padrão Composite já que o padrão está na relação recursiva entre os objetos compostos e o seu tipo. Um exemplo de uma implementação especifica do padrão Composite é o objeto JComponent da API Swing. Este objeto pode conter outros objetos do mesmo tipo numa estrutura de arvore. O Swing utiliza isso para compôr objetos visuais que serão apresentados em tela.

Self-composite

Em algumas situações especiais não existe um objeto primitivo na hierarquia ou a sua interface não se destingue da interface do objeto composto. Neste caso o objeto que representa o tipo de herarquia é simultaneamente o objeto composto e o objeto primitivo. O objeto composto é constituido de objeto iguais a si mesmo. O objeto é self-composite(auto-composto).

O exemplo clássico deste padrão é o objeto Node que representa um item em uma árvore. Nesta caso, um objeto Node contém um ou mais objetos Node. A raiz, ou seja, o primeiro elemento de todos, é também um Node. Não ha necessidade de criar vários tipos de classes já que apenas uma classe descreve completamente a hierarquia.

Na API padrão do Java encontramos o objeto java.io.File. O objeto File implementa o padrão self-composite. O objeto representa simultaneamente um arquivo e uma pasta de arquivos num sistema de arquivos ( que tem uma estrutura em árvore).
Neste caso é utilizada a mesma a interface para tratar ambos os tipos de objeto minimizando o numeto de classes necessárias para trabalhar com o sistema de arquivos.

É interessante notar que ao fundir o elemento primitivo com o composto numa só interface, mas maiorias das vezes, somos obrigados a implementar métodos que nos informam se o elemento é de um , ou de outro tipo. Por exemplo, no caso de File os métodos isFile() e isDirectory() informam se o objeto corresponde a um arquivo ou a uma pasta.

O padrão self-composite é interessante em estruturas genéricas em que estamos mais interessados em trabalhar com a estrutura do que com o que ela representa. Este padrão também diminui o numero de tipos diferentes necessários para a implementação do padrão, mas o faz à custa de despresar o polimorfismo ao introduzir métodos para determinar o tipo de componente.

Relação com outros padrões

O padrão Composite é muito comum ( especialmente se considerarmos o padrão self-composite) e é extremamente util já que estruturas em árvore são muito comuns.

Existem padrões especificamente desenhados para trabalhar sobre hierarquias de objetos como Visitor e Template Method. Outros padrões podem ser agregados para aumentar as capacidades do padrão.Por exemplo, adicionando o padrão Iterator poderiamos iterar uma arvore em profundidade com simplicidade.

Algums outros padrões podem ser entendidos como especializações ou usos do padrão Composite como Query Object , MoneyBag e Composite View (Visualização Composta), por exemplo. Composite View é um padrão util para componentes visuais. A ideia é ter uma interface gráfica montada pela composição de componentes visuais. AWT e Swing são baseados em Composite View. Composite View é também utilizado em ambiente web em que existe a composição de páginas “template” com as páginas de dados.

Referências

[1] Design Patterns: Elements of Reusable Object-Oriented Software
Erich Gamma, Richard Helm, Ralph Johnson, John M. Vlissides
URL: 1995
Addison-Wesley

Licença

Creative Commons License Sérgio Taborda
Este trabalho é licenciado sob a
Licença Creative Commons Atribuição-Uso Não-Comercial-Não a obras derivadas 3.0 Genérica .

Deixe um comentário