DEV Community

Cover image for SOLID explicado com exemplos em Java — do jeito simples que todo dev gostaria de ter aprendido
Edson Costa for Devs Norte

Posted on

SOLID explicado com exemplos em Java — do jeito simples que todo dev gostaria de ter aprendido

Ao longo da minha jornada como desenvolvedor — principalmente vindo do desenvolvimento web — sempre ouvi falar sobre SOLID. Mas foi entrando de vez no desenvolvimento mobile que esses princípios começaram a fazer um sentido muito maior no meu dia a dia.

SOLID não é um conjunto de regras rígidas, e sim um guia de boas práticas para construir sistemas mais limpos, flexíveis e fáceis de manter.
E, para explicar isso, vou usar analogias simples e exemplos reais em Java, mostrando como cada princípio se aplica no código.

Vamos direto ao ponto.


🧱 O que é SOLID?

SOLID é um acrônimo formado por cinco princípios fundamentais da programação orientada a objetos:

  • S — Single Responsibility Principle
  • O — Open/Closed Principle
  • L — Liskov Substitution Principle
  • I — Interface Segregation Principle
  • D — Dependency Inversion Principle

A ideia central é simples: projetar software que seja fácil de entender, evoluir, testar e manter.

Agora, vamos ver cada princípio na prática.


1️⃣ Single Responsibility Principle (Responsabilidade Única)

“Uma classe deve ter apenas um motivo para mudar.”

Imagine uma classe que salva usuários e também envia e-mails.
Ela faz duas coisas — e isso é um problema.

❌ Exemplo que viola o SRP

public class UserService {

    public void saveUser(User user) {
        // salva no banco
    }

    public void sendWelcomeEmail(User user) {
        // envia e-mail
    }
}
Enter fullscreen mode Exit fullscreen mode

Se qualquer parte falhar (e-mail, banco, regra de negócio), a classe inteira é afetada.

✔️ Exemplo seguindo o SRP

public class UserRepository {
    public void save(User user) {
        // salva no banco
    }
}

public class EmailService {
    public void sendWelcomeEmail(User user) {
        // envia e-mail
    }
}
Enter fullscreen mode Exit fullscreen mode

Cada classe tem sua responsabilidade, e o código fica muito mais claro e testável.


2️⃣ Open/Closed Principle (Aberto para Extensão, Fechado para Modificação)

“Você deve poder adicionar novos comportamentos sem alterar código existente.”

✔️ Exemplo com descontos

public interface Discount {
    double apply(double price);
}
Enter fullscreen mode Exit fullscreen mode
public class NoDiscount implements Discount {
    public double apply(double price) {
        return price;
    }
}

public class BlackFridayDiscount implements Discount {
    public double apply(double price) {
        return price * 0.5;
    }
}
Enter fullscreen mode Exit fullscreen mode

Precisa de um novo tipo de desconto?

Crie uma nova classe.
Nenhuma linha das anteriores precisa mudar.

Isso é Open/Closed na prática.


3️⃣ Liskov Substitution Principle (Substituição de Liskov)

“Subclasses devem poder substituir suas classes base sem quebrar o comportamento esperado.”

❌ Exemplo que quebra o princípio

public class Bird {
    public void fly() {
        System.out.println("Voando...");
    }
}

public class Penguin extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Pinguins não voam!");
    }
}
Enter fullscreen mode Exit fullscreen mode

O contrato promete que todo pássaro voa, mas o pinguim não.
Isso quebra o comportamento esperado.

✔️ Exemplo correto

Separando o que pode voar do que não pode:

public interface Bird {
    void eat();
}

public interface FlyingBird extends Bird {
    void fly();
}

public class Eagle implements FlyingBird {
    public void eat() {}
    public void fly() {}
}

public class Penguin implements Bird {
    public void eat() {}
}
Enter fullscreen mode Exit fullscreen mode

Agora, tudo faz sentido.


4️⃣ Interface Segregation Principle (Segregação de Interfaces)

“Nenhuma classe deve ser forçada a implementar métodos que não usa.”

❌ Exemplo errado

public interface Worker {
    void work();
    void eat();
}

public class Robot implements Worker {
    public void work() {}
    public void eat() {
        // robô não come...
    }
}
Enter fullscreen mode Exit fullscreen mode

O robô é obrigado a implementar algo que não faz sentido para ele.

✔️ Exemplo correto

public interface Workable {
    void work();
}

public interface Eatable {
    void eat();
}

public class Robot implements Workable {
    public void work() {}
}

public class Human implements Workable, Eatable {
    public void work() {}
    public void eat() {}
}
Enter fullscreen mode Exit fullscreen mode

Interfaces menores = classes mais limpas.


5️⃣ Dependency Inversion Principle (Inversão de Dependência)

“Dependa de abstrações, não de implementações concretas.”

❌ Exemplo errado

public class MySQLDatabase {
    public void connect() {}
}

public class UserService {
    private MySQLDatabase database = new MySQLDatabase();

    public void save(User user) {
        database.connect();
    }
}
Enter fullscreen mode Exit fullscreen mode

O serviço está acoplado ao MySQL.
Se quiser trocar para Postgres, precisa alterar o código.

✔️ Exemplo correto

public interface Database {
    void connect();
}
Enter fullscreen mode Exit fullscreen mode
public class MySQLDatabase implements Database {
    public void connect() {}
}

public class PostgresDatabase implements Database {
    public void connect() {}
}
Enter fullscreen mode Exit fullscreen mode
public class UserService {

    private Database database;

    public UserService(Database database) {
        this.database = database;
    }

    public void save(User user) {
        database.connect();
    }
}
Enter fullscreen mode Exit fullscreen mode

Agora, trocar o banco é só configurar outra implementação.


🎯 Conclusão

SOLID não é sobre “seguir regras”, e sim sobre facilitar sua vida como desenvolvedor.
Quanto mais seu sistema cresce, mais esses princípios fazem diferença.

Eles ajudam a criar:

  • código mais limpo,
  • classes mais coesas,
  • responsabilidades claras,
  • menos bugs,
  • mais testes,
  • e mais flexibilidade para evoluir o projeto.

Se você está trabalhando com Android, KMP ou qualquer arquitetura moderna (como MVVM), SOLID é um aliado poderoso.

Top comments (0)