Padrões de Projeto em Java: Guia Completo com Exemplos
Padrões de projeto (design patterns) são soluções comprovadas para problemas típicos que surgem no desenvolvimento de software. Em Java, como uma linguagem estritamente tipada e orientada a objetos, os padrões são especialmente eficazes. Eles ajudam a tornar o código flexível, reutilizável e fácil de manter. Neste artigo, abordaremos três grupos principais de padrões (de acordo com a classificação GoF): criacionais, estruturais e comportamentais — com exemplos reais em Java.
1. Padrões Criacionais (Creational Patterns)
Esses padrões gerenciam o processo de criação de objetos, tornando o sistema independente de como exatamente os objetos são criados, compostos e representados.
1.1. Singleton (Singleton)
Garante que uma classe tenha apenas uma instância e fornece um ponto de acesso global a ela. Exemplo clássico: pool de conexões com banco de dados ou logger.
public class DatabaseConnection { private static volatile DatabaseConnection instance; private String connectionString;
private DatabaseConnection(String connectionString) { this.connectionString = connectionString; }
public static DatabaseConnection getInstance(String connectionString) { if (instance == null) { synchronized (DatabaseConnection.class) { if (instance == null) { instance = new DatabaseConnection(connectionString); } } } return instance; }
public void connect() { System.out.println("Connected to: " + connectionString); }}
// UsoDatabaseConnection conn = DatabaseConnection.getInstance("jdbc:mysql://localhost:3306/mydb");conn.connect();1.2. Factory Method (Método Fábrica)
Define uma interface para criar um objeto, mas permite que subclasses alterem o tipo do objeto criado. Ideal quando o tipo exato do objeto não é conhecido antecipadamente.
interface Transport { void deliver();}
class Truck implements Transport { public void deliver() { System.out.println("Entrega por caminhão em terra"); }}
class Ship implements Transport { public void deliver() { System.out.println("Entrega por navio no mar"); }}
abstract class Logistics { abstract Transport createTransport(); public void planDelivery() { Transport t = createTransport(); t.deliver(); }}
class RoadLogistics extends Logistics { Transport createTransport() { return new Truck(); }}
class SeaLogistics extends Logistics { Transport createTransport() { return new Ship(); }}
// UsoLogistics logistics = new RoadLogistics();logistics.planDelivery(); // Saída: Entrega por caminhão em terra2. Padrões Estruturais (Structural Patterns)
Responsáveis pela composição de classes e objetos, ajudando a construir estruturas complexas a partir de componentes simples.
2.1. Adapter (Adaptador)
Permite que objetos com interfaces incompatíveis trabalhem juntos. Frequentemente usado para integrar código legado com código novo.
// Interface antigainterface OldSystem { String getDataInXML();}
// Interface novainterface NewSystem { String getDataInJSON();}
// Implementação do sistema antigoclass LegacySystem implements OldSystem { public String getDataInXML() { return "<data>Hello</data>"; }}
// Adaptadorclass XMLToJSONAdapter implements NewSystem { private OldSystem oldSystem; public XMLToJSONAdapter(OldSystem oldSystem) { this.oldSystem = oldSystem; } public String getDataInJSON() { String xml = oldSystem.getDataInXML(); return "{\\"data\\": \\"" + xml.replaceAll("<.*?>", "") + "\\"}"; }}
// E