Padrão de Projeto Decorator Adicionando funcionalidades
Cansado de ver código inchado e difícil de manter? Pois é, meu camarada, o padrão Decorator chegou para te salvar! Com ele, você adiciona novas funcionalidades aos seus objetos de forma dinâmica e elegante, sem precisar modificar as classes originais. Imagina só a flexibilidade que isso te proporciona!
O que é o Padrão de Projeto Decorator?
O Decorator é um padrão de projeto estrutural que permite adicionar responsabilidades a um objeto dinamicamente. Ele usa um sistema de encapsulamento, onde cada “decorator” envolve o objeto original, adicionando um comportamento extra. É como colocar camadas em um bolo, saca? Cada camada contribui com algo novo.
A grande vantagem é que você evita a criação de subclasses para cada combinação de funcionalidades, o que pode levar a uma explosão de classes e um código bem confuso. Com o Decorator, a coisa fica organizada e fácil de manter. Vamos combinar, ninguém merece heranças gigantes e complexas!
Por que usar o Padrão Decorator?
Se você busca um código mais flexível, extensível e fácil de manter, o Decorator é seu aliado. Ele te permite adicionar responsabilidades a objetos individuais sem afetar outros objetos da mesma classe. Além disso, ele segue o princípio do Aberto/Fechado (Open/Closed Principle), que diz que uma classe deve estar aberta para extensão, mas fechada para modificação.
- Flexibilidade: Adicione funcionalidades dinamicamente, em tempo de execução.
- Extensibilidade: Crie novas funcionalidades sem modificar o código existente.
- Manutenibilidade: Código mais limpo, organizado e fácil de entender.
- Reutilização: Decore objetos diferentes com as mesmas funcionalidades.
Decorator vs Herança

Enquanto a herança adiciona funcionalidades estaticamente, em tempo de compilação, o Decorator permite adicionar funcionalidades dinamicamente, em tempo de execução. A herança pode levar a uma hierarquia complexa e rígida, enquanto o Decorator oferece mais flexibilidade e composição. Pois é, meu amigo, menos classes e mais liberdade!
Decorator vs Composição

A composição é uma técnica onde um objeto contém outros objetos como atributos. O Decorator usa a composição para adicionar funcionalidades, mas de uma forma mais específica e padronizada. Ele cria uma cadeia de responsabilidades, onde cada decorator executa uma tarefa e passa a requisição para o próximo da cadeia. Imagina só a organização!
Implementando o Padrão Decorator: Mão na Massa
Vamos criar um exemplo prático para você entender como o Decorator funciona. Imagina que você tem uma classe Sanduiche e quer adicionar ingredientes extras, como queijo e bacon. Com o Decorator, você cria classes que “decoram” o sanduíche, adicionando esses ingredientes.
// Interface do componente
interface Sanduiche {
public function getDescricao(): string;
public function getCusto(): float;
}
// Componente concreto
class SanduicheSimples implements Sanduiche {
public function getDescricao(): string {
return "Sanduíche Simples";
}
public function getCusto(): float {
return 4.00;
}
}
// Interface do Decorator
abstract class SanduicheDecorator implements Sanduiche {
protected $sanduiche;
public function __construct(Sanduiche $sanduiche) {
$this->sanduiche = $sanduiche;
}
}
// Decorator concreto
class QueijoDecorator extends SanduicheDecorator {
public function getDescricao(): string {
return $this->sanduiche->getDescricao() . ", Queijo";
}
public function getCusto(): float {
return $this->sanduiche->getCusto() + 1.00;
}
}
class BaconDecorator extends SanduicheDecorator {
public function getDescricao(): string {
return $this->sanduiche->getDescricao() . ", Bacon";
}
public function getCusto(): float {
return $this->sanduiche->getCusto() + 2.00;
}
}
// Utilização
$sanduiche = new SanduicheSimples();
$sanduicheComQueijo = new QueijoDecorator($sanduiche);
$sanduicheCompleto = new BaconDecorator($sanduicheComQueijo);
echo $sanduicheCompleto->getDescricao() . " - R$ " . $sanduicheCompleto->getCusto(); // Sanduíche Simples, Queijo, Bacon - R$ 7.00
No código acima, criamos um sanduíche simples e, em seguida, adicionamos queijo e bacon usando os decorators. Cada decorator adiciona sua descrição e custo ao sanduíche original. Fica tranquilo, parece complicado, mas é bem simples quando você pega o jeito!
Exemplos Práticos do Decorator no Mundo Real
O Decorator é amplamente utilizado em diversas situações. Veja alguns exemplos:
- Entrada e Saída (I/O): Em Java, as classes
InputStreameOutputStreamusam decorators para adicionar funcionalidades como bufferização e compressão. - Interface Gráfica (GUI): Adicionar bordas, sombras ou outros efeitos visuais a componentes sem modificar a classe original.
- Autenticação e Autorização: Verificar permissões antes de executar um método.
Dicas de um Arquiteto Experiente
Como arquiteto de software, eu já usei o Decorator em inúmeros projetos e tenho algumas dicas para você:
- Use com moderação: Não exagere na quantidade de decorators, pois isso pode dificultar a leitura e o entendimento do código.
- Mantenha os decorators simples: Cada decorator deve ter uma responsabilidade bem definida.
- Pense na ordem dos decorators: A ordem em que os decorators são aplicados pode afetar o resultado final.
- Documente bem: Explique o propósito de cada decorator e como ele interage com os outros.
Para não esquecer:

O padrão Decorator é uma ferramenta poderosa para adicionar funcionalidades dinamicamente aos seus objetos. Use-o com sabedoria e você verá como seu código ficará mais limpo, flexível e fácil de manter.
Dúvidas Frequentes
Qual a diferença entre Decorator e Strategy?

O Decorator adiciona responsabilidades a um objeto, enquanto o Strategy define algoritmos intercambiáveis. O Decorator altera o comportamento de um objeto, enquanto o Strategy permite que um objeto varie seu comportamento.
Quando devo usar o Padrão Decorator?

Use o Decorator quando precisar adicionar responsabilidades dinamicamente a objetos individuais, sem afetar outros objetos da mesma classe. Ele é útil quando você quer evitar a criação de subclasses para cada combinação de funcionalidades.
O Decorator pode ser usado com outros padrões de projeto?
Sim, o Decorator pode ser combinado com outros padrões, como Factory, Observer e Strategy. A combinação de padrões pode resolver problemas complexos de forma elegante e eficiente.
E aí, curtiu o padrão Decorator? Espero que este guia tenha te ajudado a entender como ele funciona e como você pode usá-lo em seus projetos. Agora, coloque a mão na massa e experimente! Se tiver alguma dúvida, deixe um comentário. Compartilhe suas experiências e vamos trocar ideias!
