Vinicius Quaiato

{tecnologia, conceitos, negócios, idéias, práticas, .NET, ruby, osx, ios e algo mais}

Decorator Pattern


O padrão Decorator é um dos padrões mais simples e ao mesmo tempo bastante interessante.Ele nos permite facilmente seguir e manter o OCP - Open Closed Principle.

O padrão Decorator

A idéia principal do Pattern Decorator é prover comportamento adicional a um objeto específico e não a uma classe inteira. Desta forma decoramos um objeto com um comportamento novo, sem alterar as classes já existentes.A idéia aqui não é apenas mostrar um "Design Pattern" mas deixar claro que o conhecimento de técnicas e padrões podem nos ajudar a obter design e software mais extensível, coeso e claro. Quero mostrar apenas uma forma simples de trabalhar com abstrações, patterns e manter princípios SOLID sem criar uma estrutura rebuscada e complicada de manter ou evoluir.

O exemplo

Como exemplo vamos imaginar que temos um editor de textos html qualquer. Precisamos implementar funcionalidades de exibir texto plano, negrito, itálico e sublinhado. Podemos ainda ter qualquer combinação destes textos. Ou seja: Só plano. Só Itálico. Itálico e Negrito. Negrito e Sublinhado, etc.Não vou detalhar o passo a passo que eu segui (sim, utilizei TDD), seguem os testes e abaixo a implementação:

        [TestMethod]        
public void Texto_Vinicius_Deve_Exibir_Vinicius()        {
var texto = new TextoPlano("Vinicius");
    Assert.AreEqual("Vinicius", texto.Exibir());
    }
        [TestMethod]        
public void Texto_Vinicius_Decorado_Com_Negrito_Deve_Exibir_bViniciusb()        {
var texto = new TextoPlano("Vinicius");
    Assert.AreEqual("<b>Vinicius</b>", new Negrito(texto).Exibir());
    }
        [TestMethod]        
public void Texto_Vinicius_Decorado_Com_Negrito_Decorado_Com_italico_Deve_Exibir_ibViniciusbi()        {
var texto = new TextoPlano("Vinicius");
    Assert.AreEqual("<i><b>Vinicius</b></i>",                 new Italico(new Negrito(texto)).Exibir());
    }
        [TestMethod]        
public void Texto_Vinicius_Decorado_Com_Italico_Decorado_Com_Sublinhado_Deve_Exibir_uiViniciusiu()        {
var texto = new TextoPlano("Vinicius");
    Assert.AreEqual("<u><i>Vinicius</i></u>",                 new Sublinhado(new Italico(texto)).Exibir());
    }
    }

O comportamento do nosso código é bastante simples. Percebam como criamos um texto plano. E então decoramos este texto plano com qualquer uma das funcionalidades que queremos. Este é o intuito do padrão Decorator.A implementação disso é bastante simples, como vemos abaixo:

public interface ITexto{
string Exibir();
    }


public class TextoPlano : ITexto{    

private string text;
    
public TextoPlano(string text)    {        this.text = text;
    }
    
public string Exibir()    {
return this.text;
    }
}


public class Sublinhado : ITexto{    

private ITexto text;
    
public Sublinhado(ITexto text)    {        this.text = text;
    }
    
public string Exibir()    {
return "<u>" + this.text.Exibir() + "</u>";
    }
}


public class Italico : ITexto{    

private ITexto text;
    
public Italico(ITexto text)    {        this.text = text;
    }
    
public string Exibir()    {
return "<i>" + this.text.Exibir() + "</i>";
    }
}


public class Negrito : ITexto{    

private ITexto texto;
    
public Negrito(ITexto texto)    {        this.texto = texto;
    }
    
public string Exibir()    {
return "<b>" + this.texto.Exibir() + "</b>";
    }
}

Acho que deu pra entender que a mágica toda está na interface ITexto não é? Graças a esta abstração conseguimos decorar nossos textos da maneira que quisermos.Se amanhã surgir a necessidade de criar um "FormatoBizarroDeTexto" será simples trabalhar com ele, visto que ele apenas decorará algum objeto.Stay SOLID guys. E não se esqueçam:

Um teste é melhor que nenhum teste

Abraços,Vinicius Quaiato.

Voltar

Fork me on GitHub