originalmente publicado em http://50minutos.com.br/blog
Definição:
É um padrão que nos permite estender (decorar) dinamicamente as características de uma classe qualquer. Por características entendemos estado (state: campos e propriedades - propriedades somente em .Net) ou comportamento (behavior: métodos).
É uma alternativa à herança e tem uma diferença importante (e que torna o seu uso mais flexível) em relação àquela:
- herança é definida em tempo de compilação;
- uma classe decorada é definida em tempo de execução.
Quando usar:
- Quando temos uma classe que não queremos herdar;
- Quando temos uma classe que não pode ser herdada por ser final - em java -, sealed - em C# - ou NotInheritable - em VB.Net;
- Quando temos uma classe que não pode ser herdada por estarmos herdando de uma outra classe qualquer.

Como usar:
- Criar uma classe Decorator que implemente IComponent;
- Adicionar um campo privado do tipo IComponent;
- Adicionar um construtor que receba um IComponent e o atribua ao campo privado;
- Implementar IComponent (Operation) de acordo com a sua necessidade;
- Criar novos métodos (AddedBehavior) e/ou campos (addedState) e/ou propriedades (addedState) de acordo com a sua necessidade.
Exemplo 01:
using System;
using System.Text;
namespace _50minutos_decorator
{
class Program
{
static void Main(string[] args)
{
Pessoa pessoa;
pessoa = new Pessoa();
Console.WriteLine("usando Pessoa:");
Console.WriteLine(pessoa.Andar());
Console.WriteLine();
PessoaRapida pessoaRapida;
pessoaRapida = new PessoaRapida(pessoa);
Console.WriteLine("usando PessoaRapida:");
Console.WriteLine(pessoaRapida.Andar());
Console.WriteLine(pessoaRapida.Correr());
Console.WriteLine();
PessoaLenta pessoaLenta;
pessoaLenta = new PessoaLenta(pessoa);
Console.WriteLine("usando PessoaLenta:");
Console.WriteLine(pessoaLenta.Andar());
Console.ReadKey();
}
}
//IComponent
interface IPessoa
{
//Operation
String Andar();
}
//Component
sealed class Pessoa : IPessoa
{
//Operation
public String Andar()
{
return "andei";
}
}
//Decorator
class PessoaRapida : IPessoa
{
//Component : IComponent
IPessoa p;
public PessoaRapida(IPessoa p)
{
this.p = p;
}
//Operation
public String Andar()
{
return new StringBuilder(p.Andar())
.Append(" ")
.Append("rápido")
.ToString();
}
//AddedBehavior
public String Correr()
{
return "corri";
}
}
//Decorator
class PessoaLenta : IPessoa
{
//Component : IComponent
IPessoa p;
public PessoaLenta(IPessoa p)
{
this.p = p;
}
//Operation
public String Andar()
{
return new StringBuilder(p.Andar())
.Append(" ")
.Append("devagar")
.ToString();
}
}
}
Exemplo 02:
using System;
namespace _50minutos_decorator
{
class Program
{
static void Main(string[] args)
{
Sorvete s = new Sorvete();
Console.WriteLine("Sorvete:");
Console.WriteLine("{0:c}", s.Preco);
Console.WriteLine();
SorveteComCobertura c;
c = new SorveteComCobertura(s);
Console.WriteLine("Sorvete com cobertura:");
Console.WriteLine("{0:c}", c.Preco);
Console.WriteLine();
SorveteComBalinha b;
b = new SorveteComBalinha(s);
Console.WriteLine("Sorvete com balinha:");
Console.WriteLine("{0:c}", b.Preco);
Console.WriteLine();
SorveteComCobertura cb;
cb = new SorveteComCobertura(b);
Console.WriteLine("Sorvete com cobertura E balinha:");
Console.WriteLine("{0:c}", cb.Preco);
Console.ReadKey();
}
}
//IComponent
interface ISorvete
{
//State
double Preco { get; }
}
//Component
sealed class Sorvete : ISorvete
{
//State
public double Preco
{
get
{
return 1.50;
}
}
}
//Decorator
class SorveteComCobertura : ISorvete
{
//Component : IComponent
ISorvete s;
public SorveteComCobertura(ISorvete s)
{
this.s = s;
}
//State
public double Preco
{
get
{
return this.s.Preco + 0.50;
}
}
}
//Decorator
class SorveteComBalinha : ISorvete
{
//Component : IComponent
ISorvete s;
public SorveteComBalinha(ISorvete s)
{
this.s = s;
}
//State
public double Preco
{
get
{
return this.s.Preco + 0.75;
}
}
}
}