Padrões de Projeto em C#: guia completo com exemplos
Padrões de Projeto (Design Patterns) são soluções comprovadas para problemas típicos que surgem durante o desenvolvimento de software. No ecossistema .NET e C#, o conhecimento dos padrões é especialmente importante, pois muitos deles estão incorporados diretamente na plataforma (por exemplo, IDisposable para o padrão Dispose). Neste artigo, vamos analisar os três grupos principais de padrões de acordo com a classificação GoF (Gang of Four) com exemplos práticos em C#.
Padrões Criacionais (Creational Patterns)
Os padrões criacionais são responsáveis pela criação de objetos, tornando o sistema independente da forma como são criados, compostos e representados.
Singleton (Singleton)
Garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a ela. Em C#, é frequentemente usado para trabalhar com loggers, cache ou configuração.
public sealed class Logger{ private static readonly Lazy<Logger> _instance = new Lazy<Logger>(() => new Logger());
public static Logger Instance => _instance.Value;
private Logger() { }
public void Log(string message) { Console.WriteLine($"[{DateTime.Now}] {message}"); }}
// UsoLogger.Instance.Log("Aplicação iniciada");Factory Method (Método Fábrica)
Define uma interface para criar um objeto, mas permite que as subclasses alterem o tipo do objeto criado. É ideal para lógica que precisa ser extensível.
public interface ITransport{ void Deliver();}
public class Truck : ITransport{ public void Deliver() => Console.WriteLine("Entrega por estrada");}
public class Ship : ITransport{ public void Deliver() => Console.WriteLine("Entrega por mar");}
public abstract class Logistics{ public abstract ITransport CreateTransport();
public void PlanDelivery() { var transport = CreateTransport(); transport.Deliver(); }}
public class RoadLogistics : Logistics{ public override ITransport CreateTransport() => new Truck();}
public class SeaLogistics : Logistics{ public override ITransport CreateTransport() => new Ship();}
// UsoLogistics logistics = new RoadLogistics();logistics.PlanDelivery(); // Entrega por estradaPadrões Estruturais (Structural Patterns)
Os padrões estruturais definem maneiras de compor classes e objetos para formar estruturas maiores.
Adapter (Adaptador)
Converte a interface de uma classe em outra interface esperada pelo cliente. É frequentemente usado para integração com bibliotecas de terceiros ou código legado.
// Interface alvo (ITarget)public interface IXmlParser{ string ParseToXml(string data);}
// Classe adaptável (Adaptee)public class JsonParser{ public string ParseToJson(string data) { return $"{{\\"data\\": \\"{data}\\"}}"; }}
// Adaptadorpublic class JsonToXmlAdapter : IXmlParser{ private readonly JsonParser _jsonParser;
public JsonToXmlAdapter(JsonParser jsonParser) { _jsonParser = jsonParser; }
public string ParseToXml(string data) { var json = _jsonParser.ParseToJson(data); // Conversão simples de JSON para XML return $"<data>{data}</data>"; }}
// Usovar adapter = new JsonToXmlAdapter(new JsonParser());string xml = adapter.ParseToXml("Hello");Console.WriteLine(xml); // <data>Hello</data>Decorator (Decorador)
Adiciona dinamicamente novas responsabilidades a um objeto. Em C#, esse padrão é frequentemente implementado por meio de herança ou composição.
public interface INotifier{ void Send(string message);}
public class E