O padrão de design Decorator é usado para modificar a funcionalidade de um objeto em tempo de execução. Ao mesmo tempo, outras instâncias da mesma classe não serão afetadas por isso, garantindo que cada objeto individual obtenha o comportamento modificado. O padrão de design Decorator é um dos padrões de design estruturais (como Padrão Adapter, Padrão Bridge, Padrão Composite) e utiliza classes abstratas ou interfaces com composição para implementação.
Padrão de Design Decorator
Nós usamos herança ou composição para estender o comportamento de um objeto, mas isso é feito em tempo de compilação e é aplicável a todas as instâncias da classe. Não podemos adicionar nenhuma nova funcionalidade ou remover qualquer comportamento existente em tempo de execução – é aí que o padrão Decorator entra em cena. Suponha que queiramos implementar diferentes tipos de carros – podemos criar a interface Carro para definir o método de montagem e então podemos ter um Carro Básico, além disso, podemos estendê-lo para Carro Esportivo e Carro de Luxo. A hierarquia de implementação será semelhante à imagem abaixo. Mas se quisermos obter um carro em tempo de execução que tenha tanto as características de um carro esportivo quanto de um carro de luxo, a implementação se torna complexa e, se quisermos especificar quais características devem ser adicionadas primeiro, fica ainda mais complexo. Agora, imagine se tivermos dez tipos diferentes de carros, a lógica de implementação usando herança e composição será impossível de gerenciar. Para resolver esse tipo de situação de programação, aplicamos o padrão decorator em Java. Precisamos ter os seguintes tipos para implementar o padrão de design decorator.
-
Interface do Componente – A interface ou classe abstrata definindo os métodos que serão implementados. No nosso caso,
Carro
será a interface do componente.pacote com.journaldev.design.decorator; public interface Carro { public void montar(); }
-
Implementação do Componente – A implementação básica da interface do componente. Podemos ter a classe
CarroBasico
como nossa implementação do componente.pacote com.journaldev.design.decorator; public class CarroBasico implements Carro { @Override public void montar() { System.out.print("Carro Básico."); } }
-
Decorador – A classe Decorador implementa a interface do componente e tem uma relação HAS-A com a interface do componente. A variável do componente deve ser acessível às classes de decorador filho, então faremos essa variável protegida.
pacote com.journaldev.design.decorator; public class CarDecorator implements Car { protected Car carro; public CarDecorator(Car c){ this.carro=c; } @Override public void montar() { this.carro.montar(); } }
-
Decoradores Concretos – Estendendo a funcionalidade básica do decorador e modificando o comportamento do componente de acordo. Podemos ter classes de decorador concretas como
CarroLuxuoso
eCarroEsportivo
.pacote com.journaldev.design.decorator; public class SportsCar extends CarDecorator { public SportsCar(Car c) { super(c); } @Override public void montar(){ super.montar(); System.out.print(" Adicionando recursos de Carro Esportivo."); } }
pacote com.journaldev.design.decorator; public class LuxuryCar extends CarDecorator { public LuxuryCar(Car c) { super(c); } @Override public void montar(){ super.montar(); System.out.print(" Adicionando recursos de Carro de Luxo."); } }
Padrão de Projeto Decorator – Diagrama de Classe
Programa de Teste do Padrão de Projeto Decorator
package com.journaldev.design.test;
import com.journaldev.design.decorator.BasicCar;
import com.journaldev.design.decorator.Car;
import com.journaldev.design.decorator.LuxuryCar;
import com.journaldev.design.decorator.SportsCar;
public class DecoratorPatternTest {
public static void main(String[] args) {
Car sportsCar = new SportsCar(new BasicCar());
sportsCar.assemble();
System.out.println("\n*****");
Car sportsLuxuryCar = new SportsCar(new LuxuryCar(new BasicCar()));
sportsLuxuryCar.assemble();
}
}
Observe que o programa cliente pode criar diferentes tipos de objetos em tempo de execução e também pode especificar a ordem de execução. A saída do programa de teste acima é:
Basic Car. Adding features of Sports Car.
*****
Basic Car. Adding features of Luxury Car. Adding features of Sports Car.
Padrão de Projeto Decorator – Pontos Importantes
- O padrão de projeto decorator é útil para fornecer capacidades de modificação em tempo de execução e, portanto, é mais flexível. É fácil de manter e estender quando o número de opções é maior.
- A desvantagem do padrão de projeto decorator é que ele usa muitos objetos do mesmo tipo (decoradores).
- **Tradução para o Português:**
O padrão Decorator é muito utilizado em classes de Java IO, como FileReader, BufferedReader, etc.
Source:
https://www.digitalocean.com/community/tutorials/decorator-design-pattern-in-java-example