Los principios SOLID son fundamentales para crear código limpio, mantenible y escalable. Aquí te los explico con ejemplos sencillos en Java:
S – Principio de Responsabilidad Única (Single Responsibility Principle) #
🔍 Definición: Una clase debe tener una única razón para cambiar, es decir, solo una responsabilidad.
🛠 Ejemplo:
class ReportGenerator {
public void generateReport() {
// Genera el reporte
}
}
class ReportSaver {
public void saveReport(String report) {
// Guarda el reporte en un archivo
}
}
Aquí, ReportGenerator solo se encarga de generar el reporte y ReportSaver de guardarlo, siguiendo el principio de responsabilidad única.
O – Principio de Abierto/Cerrado (Open/Closed Principle) #
🔍 Definición: El código debe estar abierto a la extensión, pero cerrado a la modificación.
🛠 Ejemplo:
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
double area() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
double area() {
return width * height;
}
}
Aquí, se pueden añadir nuevas formas extendiendo Shape, sin necesidad de modificar la clase base.
L – Principio de Sustitución de Liskov (Liskov Substitution Principle) #
🔍 Definición: Los objetos de una clase derivada deben poder reemplazar objetos de la clase base sin alterar el comportamiento del programa.
🛠 Ejemplo:
class Bird {
public void fly() {
// Acción de volar
}
}
class Sparrow extends Bird {
@Override
public void fly() {
System.out.println("Sparrow is flying");
}
}
class Ostrich extends Bird {
@Override
public void fly() {
throw new UnsupportedOperationException("Ostriches can't fly");
}
}
Aquí, Ostrich no debería heredar de Bird si no puede volar. En su lugar, podríamos tener una jerarquía separada para aves no voladoras.
I – Principio de Segregación de Interfaces (Interface Segregation Principle) #
🔍 Definición: Una clase no debe estar obligada a implementar interfaces que no usa.
🛠 Ejemplo:
interface Printer {
void print();
}
interface Scanner {
void scan();
}
class MultiFunctionDevice implements Printer, Scanner {
@Override
public void print() {
System.out.println("Printing...");
}
@Override
public void scan() {
System.out.println("Scanning...");
}
}
Aquí, MultiFunctionDevice implementa solo las interfaces que necesita, evitando métodos innecesarios.
D – Principio de Inversión de Dependencias (Dependency Inversion Principle) #
🔍 Definición: Las clases deben depender de abstracciones, no de clases concretas.
🛠 Ejemplo:
interface Database {
void connect();
}
class MySQLDatabase implements Database {
@Override
public void connect() {
System.out.println("Connecting to MySQL...");
}
}
class DataHandler {
private Database db;
public DataHandler(Database db) {
this.db = db;
}
public void handleData() {
db.connect();
}
}
Aquí, DataHandler depende de la abstracción Database, permitiendo cambiar la implementación concreta (como MySQLDatabase) sin modificar DataHandler.
Estos principios son la base para escribir código que sea más fácil de entender, mantener y escalar. ¡Implementarlos hará tu trabajo como desarrollador mucho más eficiente! 🚀