Design Patterns C# — Aprendendo Decorator Pattern em .Net Core

Daniel Jesus
5 min readJun 20, 2020

--

Fala Nerds e fala Coders, todo dev já está se perguntou sobre Design Patterns. Portanto se você entrou neste artigo, provavelmente é porque está procurando algum artigo referente a Design Patterns e hoje resolvi escrever um post para explicar no detalhe Decorator Pattern. Já ouviu falar ?

Decorator

O Decorator ou conhecido como Wrapper é um padrão de projeto estrutural que permite que você acople novos comportamentos para objetos ao colocá-los dentro de invólucros de objetos que contém os comportamentos.

Muitas vezes pensamos de uma forma de alterar um comportamento de um objeto e a primeira coisa que vem à mente é estender uma classe. Contudo, a herança vem com algumas ressalvas sérias que você precisa estar ciente.

A herança é estática. Você não pode alterar o comportamento de um objeto existente durante o tempo de execução. Você só pode substituir todo o objeto por outro que foi criado de uma subclasse diferente.

As subclasses só podem ter uma classe pai. Na maioria das linguagens, a herança não permite que uma classe herde comportamentos de múltiplas classes ao mesmo tempo.

Uma das maneiras de superar essas ressalvas é usando Agregação ou Composição ao invés de Herança. Ambas alternativas funcionam quase da mesma maneira: um objeto tem uma referência com outro e delega alguma funcionalidade, enquanto que na herança, o próprio objeto é capaz de fazer a função, herdando o comportamento da sua superclasse.

Com essa nova abordagem você pode facilmente substituir o objeto “auxiliador” por outros, mudando o comportamento do contêiner durante o tempo de execução. Um objeto pode usar o comportamento de várias classes, ter referências a múltiplos objetos, e delegar qualquer tipo de trabalho a eles. A agregação/composição é o princípio chave por trás de muitos padrões de projeto, incluindo o Decorator. Falando nisso, vamos voltar à discussão desse padrão.

Wrapper é o apelido alternativo para o padrão Decorator que expressa claramente a ideia principal dele. Um “envoltório” é um objeto que pode ser ligado com outro objeto “alvo”. O envoltório contém o mesmo conjunto de métodos que o alvo e delega a ele todos os pedidos que recebe. Contudo, o envoltório pode alterar o resultado fazendo alguma coisa ou antes ou depois de passar o pedido para o alvo.

Quando um simples envoltório se torna um verdadeiro decorador? Como mencionei, o envoltório implementa a mesma interface que o objeto envolvido. É por isso que da perspectiva do cliente esses objetos são idênticos. Faça o campo de referência do envoltório aceitar qualquer objeto que segue aquela interface. Isso lhe permitirá cobrir um objeto em múltiplos envoltórios, adicionando o comportamento combinado de todos os envoltórios a ele.

No nosso exemplo de pizza vamos deixar o simples comportamento de BuscarTipoPizza() dentro da classe PizzaDecorator como base, mas transformar todos os métodos de BuscarTipoPizza() em decoradores.

Bom vamos olhar o exemplo que preparei para vocês:

Iremos criar um projeto em Console Application em .Net Core 3.1 para mostrar esse exemplo.

Com projeto criado, iremos criar uma classe chamada Pizza e uma interface IPizza e dentro dessa classe terá um método simples de buscar o tipo da pizza de acordo com a implementação da nossa interface de acordo trecho baixo:

Bom até ai está tranquilo né !

Agora iremos implementar o nosso pattern, pra isso precisamos implementar o base que será nossa classe PizzaDecorator que herdará a nossa interface IPizza, com isso teremos um construtor que passará a nossa interface e implementação do método BuscarTipoPizza() como virtual pois iremos utilizar o polimorfismo. De acordo código abaixo:

Agora iremos implementar os concretes do nosso pattern Decorator que serão os ingredientes extras da minha pizza e ai que acontece a mágica de alterarmos o comportamento desse objeto Pizza.

Pra isso iremos criar 3 concretes que serão as classes QueijoDecorator, CebolaDecorator e BaconDecorator que irão herdar da nossa classe base PizzaDecorator. De acordo com código abaixo:

Agora o que nos resta é chamar o método BuscarTipoPizza() que criamos na classe “Program”, de acordo com o trecho de código abaixo:

Vamos apertar o play e ver o resultado de como fica? Então bora lá:

Como podemos ver está mostrando o resultado esperado como deveria ser de acordo com a implementação na classe Pizza.

Agora vamos implementar os concretes chamando o mesmo método, mas na classe de CebolaDecorator. De acordo com alteração do código abaixo:

Agora iremos olhar o resultado final:

Podemos observar o resultado final da nossa aplicação verificamos que conseguimos alterar o comportamento do nosso objeto pizza com o Decorator pattern de acordo com a implementação de agregação ou composição ao invés de usarmos herança que esse pattern nos oferece.

Caso tenha interesse, pode assistir o vídeo no meu canal do youtube para ter o melhor entendimento desse pattern.

Conclusão

O grande objetivo deste artigo foi mostrar a implementação do Decorator Pattern.

Espera-se que este artigo tenha contribuído com o conhecido que foi passado aqui e ter ajudado muitas pessoas que tem curiosidade da implementação desse pattern.

GitHub

Deixo pra quem tem interesse o código que desenvolvemos nesse post.

--

--

Daniel Jesus
Daniel Jesus

Written by Daniel Jesus

Sênior Software Engineer, Technical Writer and Speaker, Microsoft Certified Professional

Responses (1)