Introdução: por que SOLID é importante para o desenvolvedor Java
No mundo da programação orientada a objetos, a manutenção e extensão do código tornam-se cada vez mais complexas com o tempo. Sem uma arquitetura clara, até mesmo um pequeno projeto se transforma em uma "grande bola de lama", onde alterar uma função quebra outras dez. É aqui que entram em cena os princípios SOLID — cinco regras fundamentais de design de classes, formuladas por Robert Martin (Uncle Bob).
Para o desenvolvedor Java, SOLID não é apenas teoria, mas uma ferramenta prática. Java, como uma linguagem fortemente tipada com um poderoso sistema de interfaces e herança, é ideal para implementar esses princípios. Neste artigo, vamos analisar cada princípio do ponto de vista teórico e mostrar exemplos vivos de código em Java que podem ser aplicados imediatamente em um projeto.
1. Single Responsibility Principle (Princípio da Responsabilidade Única)
Teoria
SRP afirma: uma classe deve ter apenas uma razão para mudar. Em outras palavras, a classe deve ser responsável por uma funcionalidade única e bem definida. Se uma classe faz demais, torna-se difícil de testar, modificar e reutilizar.
Prática em Java
Vamos considerar uma violação típica do SRP — uma classe que simultaneamente gerencia dados do usuário e envia notificações:
// ❌ Violação do SRPpublic class User { private String name; private String email;
public void saveToDatabase() { // Salvando no BD }
public void sendWelcomeEmail() { // Enviando email }}A solução correta é dividir a responsabilidade em duas classes:
// ✅ Cumprindo o SRPpublic class User { private String name; private String email; // Getters e Setters}
public class UserRepository { public void save(User user) { // Salvando no BD }}
public class EmailService { public void sendWelcomeEmail(User user) { // Enviando email }}Conclusão: cada classe agora tem uma única razão para mudar. User muda apenas quando a estrutura de dados muda, UserRepository muda quando a lógica do BD muda, EmailService muda quando os modelos de email mudam.
2. Open-Closed Principle (Princípio Aberto/Fechado)
Teoria
OCP afirma: as classes devem estar abertas para extensão, mas fechadas para modificação. Isso significa que novas funcionalidades devem ser adicionadas através de herança ou composição, sem tocar no código já testado.
Prática em Java
Imagine que você tem uma calculadora de descontos para diferentes tipos de clientes:
// ❌ Violação do OCPpublic class DiscountCalculator { public double calculateDiscount(String customerType, double amount) { if (customerType.equals(\"Regular\")) { return amount * 0.1; } else if (customerType.equals(\"Premium\")) { return amount * 0.2; } return 0; }}Ao adicionar um novo tipo de cliente (por exemplo, "Gold"), você teria que modificar a classe existente. A solução é usar polimorfismo:
// ✅ Cumprindo o OCPpublic interface DiscountStrategy { double calculate(double amount);}
public class RegularDiscount implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.1; }}
public class PremiumDiscount implements DiscountStrategy { @Override public double calculate(double amount) { return amount * 0.2; }}
public class DiscountCalculator { private DiscountStrategy strategy;
public DiscountCalculator(DiscountStrategy strategy) { this.strategy = strategy; }
public double calculate(double amount) {