1
Padrões: Composite (p. 163)
• Objetivo: compor objetos em estruturas de
árvores para representar relações de
parte/todo. “Composite” permite tratar
objetos individuais e composições de
maneira uniforme
Motivação
• aplicações gráficas como editores de figuras permitem
ao usuário criar diagramas complexos a partir de
componentes simples
– implementação simplista pode definir classes para
primitivas gráficas como texto e linhas e outras
classes para conterem estas classes básicas
– problema: o código que usa estas classes precisa
tratar diferentemente as classes básicas e classes
que as contem.
• “composite” descreve como usar composição
recursiva para evitar esta distinção
2
3
Motivação (2): figura
4
Aplicabilidade
• quando se quer hierarquias de objetos que se
relacionam como parte/todo
• quando se quer que “clientes” ignorem a diferença
entre composição de objetos e objetos individuais.
5
Estrutura (fig.)
Participantes
• Componente:
– define a interface para os objetos da composição
– implementa comportamento “default” para interface
comum das classes
– declara interface para acessar e manipular seus
componentes subordinados
– (opcional) define uma interface para acessar o
componente “pai” na estrutura recursiva
• Folha:
– representa objetos atômicos
– define o comportamento dos objetos básicos do sistema
6
7
Participantes (cont.)
• Composite
– define o comportamento dos componentes que tem
subordinados
– guarda referências para os subordinados
– implementa operações associadas aos elementos base
na classe Componente
• Cliente
– manipula objetos do sistema utilizando a interface de
Component
8
Colaborações
• clientes utilizam interface de Component
para interagir com estrutura
• se recipiente de uma mensagem é Leaf a
requisição é tratada diretamente
• se recipiente é Composite então geralmente
ele retransmite mensagens para seus
componentes
9
Conseqüências
• define hierarquia de classes que consistem de objetos
primitivos (Leaf) e objetos compostos (Composite).
Composição de objetos em objetos mais complexos é
recursiva
• simplifica a estrutura do cliente
• facilita a adição de novos componentes no sistema
• pode fazer a arquitetura do sistema geral demais
– facilitar adição de componentes dificulta impor restrições aos
elementos de um Composite. Com composite não se pode impor a
restrição com estrutura de tipos, mas apenas com verificações em
tempo de execução
Implementação
• referências explícitas a “pais”
– simplifica percorrer hierarquia e simplifica manutenção
da estrutura (movimentação vertical e eliminação)
– simplifica manutenção do padrão Cadeia de
Responsabilidades (“Chain of Responsibility)
– lugar usual: classe Componente
– necessário manter consistência: mudar referência a
“pai” só através das operações add e remove de
Composite
• compartilhando componentes
– possibilidade é múltiplos “pais” mas introduz
ambigüidades na medida que requisições são
propagadas na estrutura
– utilizar padrão Flyweight (p. 195)
10
11
Implementação (2)
• maximizando a interface de Component
– para permitir que clientes não precisem se concientizar
da estrutura de componentes
– providenciar implementações “default”
– conflito com princípio que cada classe deve definir
apenas operações que fazem sentido para ela (e.g. op.
em Component não faz sentido em Leaf)
• usar criatividade: Leaf é como um Component sem filhos
(default é não voltar filhos, Composite modifica)
Implementação (3)
• declaração das operações de manutenção de
descendentes
– Composite implementa add e remove
– quem delclara?
• em Component ganha-se transparência perde-se segurança (clientes
podem pedir operações sem sentido com adicionar dependentes em
Leaf)
• em Composite ganha-se segurança: operações ilegais podem ser
detectadas durante compilação, perde-se transparência
– Transparência em C++
– GetComposite (default é nil pointer)
– Add, Remove (default em Component)
12
Implementação (4)
13
• Component deve implementar uma lista de Components?
- custa espaço
• Ordenação de descendentes diretos
– padrão Iterator (pg. 257)
• Caches: Composite pode manter caches para aumentar
eficiência (e.g. “bounding box”)
– mudanças no componente invalidam as caches de seus
ascendentes (melhor quando componentes conhecem
ascendente direto)
• Quem deve remover componentes?
– sem coleta de lixo: Composite
– exceção: quando Leafs são imutáveis e compartilhados
• Qual a melhor estrutura para guardar componentes?
– depende....
Utilizações
• Interfaces de usuário
– View em Smalltalk MVC
– quase todas os sistemas para desenvolver
interfaces de usuário (ET++, InterViews)
• Compiladores:
– “RTL Smalltalk compiler framework”
• RTLExpression
• RegisterTranfer
• Finanças: portfolio agrega “assets”
• Padrão Command (pg. 233)
14
Padrões Relacionados
• Chain of Responsibility
– utiliza a ligação pai-filho
• Decorator
– usado em conjunto
• Flyweight
– permite o compartilhamento de componentes
• Iterator
– pode ser usado para enumeração de Composite
• Visitor
– concentra operações e comportamento que de outra
maneira seriam distribuídas entre as classes Composite
e Leaf
15
Download

Padrões:Composite - IME-USP