O padrão Decorator permite adicionar dinamicamente novas responsabilidades a um objeto, decorando-o com outros objetos. Isso é útil quando se deseja estender a funcionalidade de um objeto sem alterar sua classe. O padrão é aplicado na cafeteria Starbuzz para permitir que cafés sejam decorados com itens adicionais como leite e chocolate, calculando o preço total.
3. Padrão Decorator
Starbuzz Coffee, uma cafeteria famosa,
deseja atualizar seu sistema para corresponder a sua oferta de bebidas.
Juliane Silva
3
4. Padrão Decorator
O que a StarBuzz tem, por enquanto, é...
calcularPreco() é abstrato,
para que as subclasses definam sua implementação.
Juliane Silva
4
5. Padrão Decorator
Porém, a StarBuzz não oferece SÓ isso...
Os adicionais são o
atrativo desse lugar!
E, como é cobrado um valor por adicional,
é preciso incluí-los no sistema.
Juliane Silva
5
7. Padrão Decorator
Solução 1: 1 classe para cada combinação.
Tradicional + Leite; Tradicional + Espuma; Tradicional + Leite + Espuma, ...
Cada classe calcula o preço
do café juntamente com o
adicional pedido.
Juliane Silva
E quando o preço do leite aumentar?
E quando um novo adicional entrar?
E quando? E quando?...
7
8. Padrão Decorator
Solução 2: variáveis para representar os adicionais.
leite, espuma, creme, chocolate, ...
Calcula o total dos
adicionais.
E se o preço do leite aumentar?
E se chá gelado entrar? Sem
leite, sem creme, sem nada.
E se o cliente quiser 2x creme?
Calcula o preço da bebida
+ adicionais (super.calcular
Preco()).
Juliane Silva
8
10. Padrão Decorator
Solução 3 (a melhor entre elas):
PADRÃO DECORATOR!
Considera os princípio de herança/composição e aberto/fechado.
Juliane Silva
10
11. Padrão Decorator
Solução 3: padrão Decorator.
Vamos começar com uma bebida e “decorá-la” no tempo de execução.
1. Pegar um objeto CafeTradicional.
3. Decorá-lo com um objeto Leite.
2. Decorá-lo com um objeto Choco-
4. Chamar calcularPreco() e contar
late.
Juliane Silva
com a delegação para adicionar
o preço da bebida+adicionais.
11
12. Padrão Decorator
Mas como se decora?
1. Começamos com o objeto CafeTradicional.
calcularPreco()
CafeTradicional
2. Criamos um objeto Chocolate e
englobamos CafeTradicional nele.
calcularPreco()
CafeTradicional
3. Criamos um decorador Leite e
colocamos Chocolate dentro.
calcularPreco()
CafeTradicional
calcularPreco()
Chocolate
calcularPreco()
Leite
calcularPreco()
Chocolate
Juliane Silva
12
13. Padrão Decorator
E como se calcula o preço de tudo isso?
calcularPreco()
CafeTradicional
3. Chocolate chama calcularPreco() de CafeTradicional.
2. Leite chama calcularPreco()
de Chocolate.
1. Chamamos calcularPreco()
do decorador externo, Leite.
Juliane Silva
calcularPreco()
Chocolate
calcularPreco()
Leite
4. CafeTradicional retorna seu valor.
5. Chocolate retorna seu valor
+ CafeTradicional
6. Leite retorna seu valor +
Chocolate, que é o valor total.
13
14. Padrão Decorator
Enfim, temos a solução para o nosso problema!
Que é representada assim...
Componentes aos quais adicionamos dinamicamente um
novo comportamento.
Os decoradores precisam
da mesma interface dos
componentes,
porque
ficam no lugar deles.
Os decoradores emglobam um componente.
Juliane Silva
14
16. Padrão Decorator
Os decoradores precisam ser do mesmo tipo que as bebidas.
Bebida que estamos
englobando.
Onde calculamos o preço do
Chocolate+CafeTradicional.
Juliane Silva
16
18. Padrão Decorator
Formalmente...
• Os decoradores têm o mesmo supertipo que os
objetos que eles decoram;
• É permitido usar 1/+ decoradores para englobar
um objeto;
• Os objetos podem ser decorados dinamicamente em tempo de execução.
Juliane Silva
18
19. Padrão Decorator
E, ao contrário da herança, que aplica
funcionalidade a todos os objetos dela, ele permite
aplicar funcionalidades a um objeto específico.
Juliane Silva
19