Os padrões de design são soluções recorrentes para problemas comuns em design de software. No contexto do Java, uma linguagem orientada a objetos, a aplicação correta de design patterns pode melhorar a modularidade, a reusabilidade e a manutenção do código. Neste guia, exploraremos alguns design patterns com exemplos práticos em projetos Java.
1. Singleton: Garantindo uma Única Instância
O padrão Singleton é usado para garantir que uma classe tenha apenas uma instância e fornece um ponto global de acesso a essa instância.
public class Singleton {
private static Singleton instancia;
private Singleton() {
// Construtor privado para evitar instâncias múltiplas
}
public static synchronized Singleton getInstance() {
if (instancia == null) {
instancia = new Singleton();
}
return instancia;
}
}
2. Factory Method: Delegando a Criação de Objetos
O padrão Factory Method define uma interface para criar um objeto, mas deixa as subclasses alterarem o tipo de objetos que serão criados.
public interface Animal {
void fazerSom();
}
public class Cachorro implements Animal {
@Override
public void fazerSom() {
System.out.println("Au Au!");
}
}
public class Gato implements Animal {
@Override
public void fazerSom() {
System.out.println("Miau!");
}
}
public interface AnimalFactory {
Animal criarAnimal();
}
public class CachorroFactory implements AnimalFactory {
@Override
public Animal criarAnimal() {
return new Cachorro();
}
}
public class GatoFactory implements AnimalFactory {
@Override
public Animal criarAnimal() {
return new Gato();
}
}
3. Observer: Reagindo a Mudanças de Estado
O padrão Observer define uma dependência um para muitos entre objetos, de modo que quando um objeto muda de estado, todos os seus dependentes são notificados e atualizados automaticamente.
import java.util.ArrayList;
import java.util.List;
public interface Observador {
void notificar(String mensagem);
}
public class Assunto {
private List<Observador> observadores = new ArrayList<>();
public void adicionarObservador(Observador observador) {
observadores.add(observador);
}
public void removerObservador(Observador observador) {
observadores.remove(observador);
}
public void notificarObservadores(String mensagem) {
for (Observador observador : observadores) {
observador.notificar(mensagem);
}
}
}
4. Strategy: Definindo Famílias de Algoritmos
O padrão Strategy define uma família de algoritmos, encapsula cada um deles e os torna intercambiáveis. Permite que o algoritmo varie independentemente dos clientes que o utilizam.
public interface Algoritmo {
void executar();
}
public class AlgoritmoConcretoA implements Algoritmo {
@Override
public void executar() {
System.out.println("Executando Algoritmo A");
}
}
public class AlgoritmoConcretoB implements Algoritmo {
@Override
public void executar() {
System.out.println("Executando Algoritmo B");
}
}
public class Cliente {
private Algoritmo algoritmo;
public Cliente(Algoritmo algoritmo) {
this.algoritmo = algoritmo;
}
public void executarAlgoritmo() {
algoritmo.executar();
}
public void setAlgoritmo(Algoritmo algoritmo) {
this.algoritmo = algoritmo;
}
}
Conclusão:
O uso de design patterns em projetos Java pode melhorar a qualidade e a manutenção do código, promovendo boas práticas de design orientado a objetos. Além dos exemplos apresentados, existem muitos outros design patterns disponíveis, cada um com suas aplicações específicas. Ao compreender e aplicar esses padrões, os desenvolvedores podem criar sistemas mais flexíveis, extensíveis e fáceis de manter.