Os padrões de projetos ajudam estruturar programas de maneiras mais flexíveis, fáceis de entender e manter. Através deles sistemas são construídos com boas qualidades de design orientado à objetos(OO). Eles nos fornecem soluções gerais para problemas de projeto. Esse artigo explica o padrão decorator mostrando seu uso e estrutura aplicada no contexto de um programa de um Food Truck de Açaí.
As técnicas de decoração possibilita dar novas responsabilidades aos objetos sem fazer mudança de código nas classes básicas.
A utilização da herança é poderosa, porém nem sempre leva aos designs mais flexíveis ou sustentáveis. Os comportamentos podem ser “herdados” em tempo de execução por meio da composição e da delegação.
Quando um comportamento é herdado através de subclasses, esse comportamento é definido estaticamente no tempo de compilação. Dessa forma, todas as subclasses devem herdar o mesmo comportamento. Todavia, estendendo o comportamento de um objeto por meio da composição possibilita alterar seu comportamento dinamicamente em tempo de execução. Utilizando essa técnica, é possível adicionar novas responsabilidades a objetos.
Com a possibilidade de escolher um comportamento dinamicamente, pode-se criar um novo comportamento criando uma nova classe em vez de alterar o código existente. Como o código existente não está sendo alterado, as chances de introduzir erros no código preexistente são muito menores.
No padrão Decorator é utilizada herança para que os decoradores tenham o mesmo tipo que os objetos que eles irão decorar. Porém, não é utilizada a herença para obter o comportamento. Ao compor um decorador com um componente é adicionado um novo comportamento. Portanto, através da composição de objetos é adquirido um novo comportamento.
O diagrama de classe do padrão Decorator é mostrado abaixo:
Em seguida, é exibida a estrutura aplicada no problema do açaí:
Como exemplo, vamos considerar o pedido de um cliente o qual pediu um açaí com morango, banana e granola.
Os passos para construir esse pedido com decoradores são:
Açaí decorado com morango, banana e granola continua sendo uma comida (Food). Logo, podemos fazer com ela tudo o que podemos fazer com o Acai, inclusive chamar seu método cost().
Para calcular o custo do cliente, é preciso chamar o método cost() no decorador externo, Granola, e Granola vai delegar o cálculo do custo para o objeto que decora. Depois que obtiver um custo, ela irá adicionar o seu custo e devolver o valor final que o cliente deve pagar. A imagem abaixo explica as etapas com mais detalhes:
Código da classe Food:
package com.programacao4devs.decorator.model;
public abstract class Food {
String description = "General Food";
public String getDescription() {
return this.description;
}
public abstract double cost();
}
Código da classe Acai:
package com.programacao4devs.decorator.model;
public class Acai extends Food {
public Acai() {
description = "Açaí";
}
@Override
public double cost() {
return 10.00;
}
}
Código da classe ItemDecorator:
package com.programacao4devs.decorator.model.item;
import com.programacao4devs.decorator.model.Food;
public abstract class ItemDecorator extends Food {
public abstract String getDescription();
}
Código da classe Morango:
package com.programacao4devs.decorator.model.item;
import com.programacao4devs.decorator.model.Food;
public class Morango extends ItemDecorator {
Food food;
public Morango(Food food) {
this.food = food;
}
@Override
public String getDescription() {
return food.getDescription() + ", Morango";
}
@Override
public double cost() {
return 2.00 + food.cost();
}
}
Código da classe AcaiFoodTruck para executar o teste:
public class AcaiFoodTruck {
public static void main (String args[]) {
Food acaiSemItem = new Acai();
System.out.println(acaiSemItem.getDescription() + " R$ " + acaiSemItem.cost());
Food acaiComItens = new Acai();
acaiComItens = new Morango(acaiComItens);
acaiComItens = new Banana(acaiComItens);
acaiComItens = new Granola(acaiComItens);
System.out.println(acaiComItens.getDescription() + " R$ " + acaiComItens.cost());
}
}
Resultado mostrado no Console:
Açaí R$ 10.0
Açaí, Morango, Banana, Granola R$ 16.0
Download do código completo em: https://github.com/programacao4devs/padrao-decorator
Os princípios OO utilizados no padrão decorator:
Inscreva seu nome e email na Programacao4Devs para receber atualizações de novos artigos, tutoriais e dicas.
Sua inscrição foi registrada. Obrigado!