Backend
Padrão de Projeto Decorator: Adicionando Funcionalidades sem Quebrar sua Arquitetura
Gabriel Bertonsin DEV Community
2 views
Se você já trabalhou com orientação a objetos por algum tempo, provavelmente já se deparou com este dilema: como adicionar novas funcionalidades a um objeto sem criar uma explosão de subclasses? Imagine um sistema de componentes gráficos onde você precisa combinar bordas, sombras, cores e efeitos de diferentes formas. Criar uma subclasse para cada combinação possível rapidamente se torna insustentável.
É exatamente para resolver esse tipo de problema que existe o Decorator, um dos padrões de projeto estruturais mais elegantes do catálogo GoF (Gang of Four).
Neste artigo, vou explicar o que é o padrão Decorator, quando ele deve ser usado e como implementá-lo na prática com um exemplo completo em Java.
O que é o padrão Decorator?
O Decorator é um padrão de design estrutural que permite adicionar comportamento a objetos individuais de forma dinâmica e transparente, sem afetar outros objetos da mesma classe.
Em vez de estender uma classe para adicionar uma nova responsabilidade (o que gera herança rígida e múltiplas subclasses), o Decorator envolve o objeto original com uma camada adicional de comportamento — como se fosse uma "embalagem" que soma funcionalidades sem alterar a estrutura interna do objeto decorado.
O resultado é um sistema muito mais flexível e modular, no qual novas combinações de comportamento podem ser criadas em tempo de execução, simplesmente combinando decoradores diferentes.
Vantagens do Decorator
Flexibilidade e modularidade: permite estender o comportamento de objetos individuais sem afetar os demais.
Evita a explosão de subclasses: ao invés de criar uma classe para cada combinação de funcionalidades, você combina decoradores.
Responsabilidade única: cada decorador cuida de uma única responsabilidade, mantendo o código mais limpo e coeso.
Quando usar o Decorator?
Esse padrão é especialmente útil quando:
Você precisa adicionar responsabilidades a objetos dinamicamente, sem modificar seu código-fonte.
Você quer evitar a criação de subclasses excessivas para representar cada combinação possível de comportamentos.
Você busca uma alternativa à herança para estender funcionalidades de forma mais flexível.
Estrutura do Padrão
O Decorator é composto por quatro elementos principais:
1. Componente (Component)
Define a interface comum para os objetos que podem receber responsabilidades adicionais. É o contrato que tanto os componentes concretos quanto os decoradores devem seguir.
// Componente
interface Component {
void draw();
}
2. Componente Concreto (Concrete Component)
Implementa o comportamento básico do componente — é o objeto "puro", sem nenhuma decoração aplicada ainda.
// Componente Concreto
class Button implements Component {
public void draw() {
System.out.println("Drawing a button");
}
}
3. Decorador (Decorator)
Essa é a peça central do padrão. O decorador:
Mantém uma referência para um objeto do tipo Component.
Implementa a mesma interface do componente base, garantindo que possa ser usado no lugar dele.
Encapsula o componente original e adiciona um comportamento extra.
Pode ser estendido por subclasses para implementar responsabilidades específicas.
// Decorador
abstract class BorderDecorator implements Component {
protected Component component;
public BorderDecorator(Component component) {
this.component = component;
}
public void draw() {
component.draw();
drawBorder();
}
protected abstract void drawBorder();
}
Note que o método draw() primeiro chama o comportamento original (component.draw()) e depois adiciona o novo comportamento (drawBorder()). Essa é a essência do padrão: compor comportamentos em camadas.
4. Decorador Concreto (Concrete Decorator)
Estende o decorador abstrato e implementa a funcionalidade específica que será adicionada.
// Decorador Concreto
class RedBorderDecorator extends BorderDecorator {
public RedBorderDecorator(Component component) {
super(component);
}
protected void drawBorder() {
System.out.println("Drawing a red border");
}
}
Colocando tudo em prática
Com as classes definidas, podemos ver o padrão em ação:
public class Main {
public static void main(String[] args) {
// Componente original
Component button = new Button();
// Decorando o componente original com uma borda vermelha
Component decoratedButton = new RedBorderDecorator(button);
// Desenhando o componente decorado
decoratedButton.draw();
}
}
Saída esperada:
Drawing a button
Drawing a red border
Perceba que o botão original não foi alterado. Ele continua existindo como uma implementação independente. A borda vermelha foi adicionada dinamicamente, "envolvendo" o botão em uma nova camada de comportamento. Se amanhã precisarmos de um botão com borda azul, ou com borda e sombra combinadas, basta criar (ou combinar) novos decoradores — sem tocar na classe Button.
Por que isso importa?
O grande ganho do Decorator está em respeitar o princípio Aberto/Fechado (Open/Closed Principle): as classes ficam abertas para extensão, mas fechadas para modificação. Isso significa que podemos adicionar novos comportamentos ao sistema sem correr o risco de quebrar código já existente e testado.
Além disso, como os decoradores podem ser empilhados (um decorador pode envolver outro decorador), é possível construir combinações complexas de comportamento a partir de peças simples e reutilizáveis — algo muito mais elegante do que uma árvore de herança cheia de subclasses.
Conclusão
O padrão Decorator é uma ferramenta poderosa para quem busca flexibilidade no design de sistemas orientados a objetos. Ao substituir a herança rígida por composição dinâmica, ele permite adicionar responsabilidades a objetos de forma modular, reutilizável e sem efeitos colaterais sobre outras instâncias da mesma classe.
Esse padrão é amplamente utilizado em bibliotecas e frameworks conhecidos — por exemplo, o próprio java.io do Java (como BufferedReader envolvendo um FileReader) é um exemplo clássico de Decorator aplicado na prática.
Entender e saber aplicar o Decorator é um passo importante para escrever código mais limpo, extensível e alinhado com boas práticas de design orientado a objetos.
Read original: https://dev.to/gabriel_berton_brito/padrao-de-projeto-decorator-adicionando-funcionalidades-sem-quebrar-sua-arquitetura-c0h
← Previous
XML Configuration Mode: Decoupling Your API Catalog from Business Code
Next →
Milestone Reached: YINI Syntax Highlighting Is Now on the VS Code Marketplace
Related
Production API Key Rotation Explained: 6 Least-Privilege Checks for Node.js GitHub Actions
Backend
0
Dev.to (EN Zone)
XML Configuration Mode: Decoupling Your API Catalog from Business Code
Backend
2
DEV Community
Build a small OpenOSRS plugin in Java
Backend
1
DEV Community
[showoff Saturday] I got hooked on Advent of Code and wanted it all year, so I built a site that gives everyone the same coding challenge every day
Backend
2
Reddit r/webdev
Comments0
No comments yet — be the first