Skip to content

🌿 SOLID


🟠 Single Responsibility Principle (SRP) Princípio da Responsabilidade Única:

 Uma classe deve ter apenas um motivo para mudar, ou seja, ela deve ter apenas uma responsabilidade.
//exemplo ruim: Problema: A classe Relatorio tem duas responsabilidades: gerar relatório e salvar em arquivo.
class Relatorio {
    public void gerarRelatorio() {
        // gera relatório
    }

    public void salvarNoArquivo() {
        // salva relatório em arquivo
    }
}

//exemplo correto
class Relatorio {
    public void gerarRelatorio() {
        // gera relatório
    }
}

class RelatorioArquivo {
    public void salvar(Relatorio relatorio) {
        // salva relatório em arquivo
    }
}
//Cada classe tem uma única responsabilidade: gerar ou salvar.


Open/Closed Principle (OCP) 🟠 Princípio Aberto/Fechado:

 Uma classe deve estar aberta para extensão, mas fechada para modificação.
//exemplo ruim: Toda vez que você quiser adicionar uma operação nova, precisa modificar a classe.
class Calculadora {
    public double calcular(String tipo, double a, double b) {
        if (tipo.equals("SOMA")) return a + b;
        else if (tipo.equals("MULT")) return a * b;
        return 0;
    }
}

//exemplo correto:
interface Operacao {
    double calcular(double a, double b);
}

class Soma implements Operacao {
    public double calcular(double a, double b) {
        return a + b;
    }
}

class Multiplicacao implements Operacao {
    public double calcular(double a, double b) {
        return a * b;
    }
}

class Calculadora {
    public double calcular(Operacao operacao, double a, double b) {
        return operacao.calcular(a, b);
    }
}
Agora, para adicionar uma nova operação, basta criar uma nova classe que implemente Operacao, sem modificar a Calculadora.


Liskov Substitution Principle (LSP) 🟠 Princípio da Substituição de Liskov:

 Classes derivadas devem poder ser substituídas por suas classes base sem quebrar o funcionamento do programa.
Exemplo ruim:Pinguim não pode substituir Ave porque lança exceção ao chamar voar().

class Ave {
    public void voar() {}
}

class Pinguim extends Ave {
    public void voar() {
        throw new UnsupportedOperationException("Pinguins não voam!");
    }
}

Exemplo correto: 

interface Ave {
}

interface AveQueVoa {
    void voar();
}

class Pardal implements AveQueVoa {
    public void voar() {
        System.out.println("Pardal voando");
    }
}

class Pinguim implements Ave {
    // Pinguim não implementa AveQueVoa
}

//Cada classe implementa apenas o que faz sentido, evitando violações do LSP.


Interface Segregation Principle (ISP) 🟠 Princípio da Segregação de Interfaces:

 Muitas interfaces específicas são melhores que uma interface única e genérica.
Exemplo ruim: Robô não tira férias, mas é forçado a implementar.
interface Trabalhador {
    void trabalhar();
    void tirarFerias();
}

class Funcionario implements Trabalhador {
    public void trabalhar() { }
    public void tirarFerias() { }
}

class Robo implements Trabalhador {
    public void trabalhar() { }
    public void tirarFerias() {
        throw new UnsupportedOperationException();
    }
}

Exemplo correto: 
interface Trabalhador {
    void trabalhar();
}

interface Ferias {
    void tirarFerias();
}

class Funcionario implements Trabalhador, Ferias {
    public void trabalhar() { }
    public void tirarFerias() { }
}

class Robo implements Trabalhador {
    public void trabalhar() { }
}

//Agora as classes implementam apenas o que é relevante.


Dependency Inversion Principle (DIP) 🟠 Princípio da Inversão de Dependência:

 Dependa de abstrações, não de implementações concretas.
Exemplo ruim: UsuarioService depende de uma implementação concreta (MySQLDatabase).
class MySQLDatabase {
    public void salvar() {}
}

class UsuarioService {
    private MySQLDatabase db = new MySQLDatabase();

    public void salvarUsuario() {
        db.salvar();
    }
}
// Exemplo correto: UsuarioService agora depende de uma abstração (Database) e não de uma implementação concreta.

interface Database {
    void salvar();
}

class MySQLDatabase implements Database {
    public void salvar() {}
}

class UsuarioService {
    private Database db;

    public UsuarioService(Database db) {
        this.db = db;
    }

    public void salvarUsuario() {
        db.salvar();
    }
}

// Uso
Database db = new MySQLDatabase();
UsuarioService service = new UsuarioService(db);
service.salvarUsuario();


Princípio X Objetivo

  • SRP Uma classe = uma responsabilidade
  • OCP Aberta para extensão, fechada para modificação
  • LSP Subclasses podem substituir a superclasse
  • ISP Interfaces específicas > interface única gigante
  • DIP Dependa de abstrações, não de concretos