Skip to the content.
Skip to the content.

Decorator Pattern: Entendendo o Padrão de Projeto Decorator 

O Padrão de Projeto Decorator é uma solução muito bacana para adicionar funcionalidades a objetos de forma dinâmica sem que seja necessário alterar o código original, vamos entender como ele funciona e explorar um exemplo prático e ver como é simples de implementá-lo.

O que é o Padrão Decorator?

O padrão Decorator é um padrão de design estrutural que permite adicionar funcionalidades a objetos de forma dinâmica, ou seja, em tempo de execução, sem modificar o código original da classe. Ele envolve a criação de uma interface ou classe abstrata que define o comportamento básico, e classes concretas que implementam essa interface e adicionam funcionalidades extras.

Imagine que temos uma classe que é responsável por enviar notificações, mas quando precisamos adicionar novas funcionalidades e não queremos modificar o código original, com esse cenário em mente, vamos aplicar o padrão Decorator.

copy
public interface INotificacao
{
	void Enviar(string mensagem);
}

public class Notificacao : INotificacao
{
	public void Enviar(string mensagem)
	{
		Console.WriteLine($"Notificação: {mensagem}");
	}
}

Essa classe Notificacao tem um método Enviar que simplesmente imprime uma mensagem. Agora, suponha que queremos adicionar funcionalidades como enviar notificações por e-mail e uma retentativa de envio em caso de falha, mas sem alterar a classe original Notificacao. Aqui podemos usar o padrão Decorator.

copy
public abstract class NotificacaoDecorator : INotificacao
{
	protected INotificacao _notificacao;

	public NotificacaoDecorator(INotificacao notificacao)
	{
		_notificacao = notificacao;
	}

	public void Enviar(string mensagem)
	{
		_notificacao.Enviar(mensagem);
	}
}

public class NotificacaoEmail : NotificacaoDecorator
{
	public NotificacaoEmail(INotificacao notificacao) : base(notificacao) { }

	public override void Enviar(string mensagem)
	{
		base.Enviar(mensagem);
		Console.WriteLine($"Enviando e-mail: {mensagem}");
	}
}

public class RetentativaNotificacao : NotificacaoDecorator
{
	public RetentativaNotificacao(INotificacao notificacao) : base(notificacao) { }

	public override void Enviar(string mensagem)
	{
		try
		{
			base.Enviar(mensagem);
		}
		catch (Exception)
		{
			Console.WriteLine("Falha ao enviar notificação, tentando novamente...");
			base.Enviar(mensagem);
		}
	}
}

Já temos duas classes decoradoras, a classe NotificacaoEmail para enviar e-mail, e a classe RetentativaNotificacao que vai tentar reenviar a notificação em caso de falha, agora vamos ver como usar essas classes:

copy
class Program
{
	static void Main(string[] args)
	{
		INotificacao notificacao = new Notificacao();
		INotificacao notificacaoComEmail = new NotificacaoEmail(notificacao);
		INotificacao notificacaoComRetentativa = new RetentativaNotificacao(notificacaoComEmail);

		notificacaoComRetentativa.Enviar("Olá, esta é uma notificação!");
	}
}

No código acima, criamos uma instância da classe Notificacao, depois a decoramos com NotificacaoEmail e RetentativaNotificacao. Quando chamamos o método Enviar, ele executa a lógica original e as funcionalidades adicionais de forma dinâmica.

Vantagens do Padrão Decorator

Onde encontramos o Padrão Decorator no dia a dia?

No asp.net core, esse padrão é utilizado em middlewares, onde cada middleware pode adicionar funcionalidades adicionais ao pipeline de requisições sem modificar o código original do servidor. Essa aplicação do padrão Decorator, é pessoalmente uma das minhas favoritas, porque podemos adicionar funcionalidades como autenticação, logging, compressão, entre outras, de forma modular e reutilizável.