Curso de Java 18

Descubriendo la Elegancia del Código: Un Viaje a través de los Patrones de Diseño en Java

En el vasto universo de la programación, los patrones de diseño son como las constelaciones que guían a los programadores hacia soluciones elegantes y eficientes. En esta odisea, exploraremos el fascinante mundo de los patrones de diseño en Java, desglosando conceptos y desvelando los secretos detrás de patrones de creación, estructurales y de comportamiento.

Concepto de Patrón de Diseño: Diseñando con Elegancia

Un patrón de diseño es una solución general y reutilizable para un problema común en el diseño de software. Estos patrones no son fragmentos de código listos para copiar y pegar, sino más bien pautas que pueden adaptarse y aplicarse a situaciones específicas.

Patrones de Creación: Dando Forma a los Objetos

Singleton: Un Único Guardián

public class Singleton {
    private static Singleton instancia;

    private Singleton() {}

    public static Singleton getInstancia() {
        if (instancia == null) {
            instancia = new Singleton();
        }
        return instancia;
    }
}

El patrón Singleton garantiza que una clase tenga solo una instancia y proporciona un punto de acceso global a ella.

Builder: Construyendo con Precisión

public class Producto {
    private String parte1;
    private String parte2;

    // Getters y setters
}

public class ConstructorDeProducto {
    private Producto producto = new Producto();

    public ConstructorDeProducto construirParte1(String parte1) {
        producto.setParte1(parte1);
        return this;
    }

    public ConstructorDeProducto construirParte2(String parte2) {
        producto.setParte2(parte2);
        return this;
    }

    public Producto construir() {
        return producto;
    }
}

El patrón Builder separa la construcción de un objeto complejo de su representación, permitiendo la creación de diferentes representaciones.

Factory Method: La Fábrica de Objetos

public interface Producto {
    void operacion();
}

public class ProductoConcreto implements Producto {
    @Override
    public void operacion() {
        // Implementación específica
    }
}

public interface Creador {
    Producto crearProducto();
}

public class CreadorConcreto implements Creador {
    @Override
    public Producto crearProducto() {
        return new ProductoConcreto();
    }
}

El patrón Factory Method define una interfaz para crear un objeto, pero deja que las subclases alteren el tipo de objetos que se crearán.

Patrones Estructurales: Construyendo el Esqueleto

Adapter: Adaptando para la Armonía

public interface Objetivo {
    void operacion();
}

public class Adaptable {
    public void operacionDiferente() {
        // Lógica específica
    }
}

public class Adaptador implements Objetivo {
    private Adaptable adaptable;

    public Adaptador(Adaptable adaptable) {
        this.adaptable = adaptable;
    }

    @Override
    public void operacion() {
        adaptable.operacionDiferente();
    }
}

El patrón Adapter permite que interfaces incompatibles trabajen juntas.

Decorator: Envuelto en Elegancia

public interface Componente {
    void operacion();
}

public class ComponenteConcreto implements Componente {
    @Override
    public void operacion() {
        // Lógica específica
    }
}

public abstract class Decorador implements Componente {
    protected Componente componente;

    public Decorador(Componente componente) {
        this.componente = componente;
    }

    @Override
    public void operacion() {
        componente.operacion();
    }
}

El patrón Decorator permite añadir funcionalidades a objetos dinámicamente.

Facade: Simplificando la Fachada

public class SubsistemaA {
    public void operacionA() {
        // Lógica específica
    }
}

public class SubsistemaB {
    public void operacionB() {
        // Lógica específica
    }
}

public class Fachada {
    private SubsistemaA subsistemaA;
    private SubsistemaB subsistemaB;

    public Fachada() {
        this.subsistemaA = new SubsistemaA();
        this.subsistemaB = new SubsistemaB();
    }

    public void operacionCompleja() {
        subsistemaA.operacionA();
        subsistemaB.operacionB();
    }
}

El patrón Facade proporciona una interfaz unificada para un conjunto de interfaces en un subsistema.

Patrones de Comportamiento: Guiando las Interacciones

Observer: Vigilando los Cambios

import java.util.ArrayList;
import java.util.List;

public interface Observador {
    void actualizar(String mensaje);
}

public class Sujeto {
    private List observadores = new ArrayList<>();

    public void agregarObservador(Observador observador) {
        observadores.add(observador);
    }

    public void notificarObservadores(String mensaje) {
        for (Observador observador : observadores) {
            observador.actualizar(mensaje);
        }
    }
}

public class ObservadorConcreto implements Observador {
    @Override
    public void actualizar(String mensaje) {
        // Lógica específica
    }
}

El patrón Observer define una dependencia uno a muchos entre objetos, de modo que cuando un objeto cambia su estado, todos sus dependientes son notificados y actualizados automáticamente.

Strategy: Estrategias para el Éxito

public interface Estrategia {
    void ejecutar();
}

public class Contexto {
    private Estrategia estrategia;

    public void setEstrategia(Estrategia estrategia) {
        this.estrategia = estrategia;
    }

    public void ejecutarEstrategia() {
        estrategia.ejecutar();
    }
}

public class EstrategiaConcreta implements Estrategia {
    @Override
    public void ejecutar() {
        // Lógica específica
    }
}

El patrón Strategy define una familia de algoritmos, encapsula cada uno de ellos y los hace intercambiables.

Template Method: Siguiendo la Plantilla

public abstract class Plantilla {
    public final void operacionTemplate() {
        paso1();
        paso2();
        paso3();
    }

    protected abstract void paso1();
    protected abstract void paso2();
    protected abstract void paso3();
}

public class PlantillaConcreta extends Plantilla {
    @Override
    protected void paso1() {
        // Implementación específica
    }

    @Override
    protected void paso2() {
        // Implementación específica
    }

    @Override
    protected void paso3() {
        // Implementación específica
    }
}

El patrón Template Method define el esqueleto de un algoritmo en una operación, delegando algunos de sus pasos a las subclases.

Conclusión: Tejiendo la Tela del Software Elegante

En conclusión, los patrones de diseño son herramientas esenciales para cualquier arquitecto de software. Ya sea que estemos dando forma a objetos, estructurando nuestro código o guiando las interacciones, los patrones nos proporcionan un conjunto probado de soluciones para problemas comunes. Al adoptar estos patrones, no solo mejoramos la eficiencia y flexibilidad de nuestro código, sino que también cultivamos una base sólida para el desarrollo de software robusto y mantenible.

Compartir

Compartir

Suscribirse
Notificar de
guest

0 Comentarios
Comentarios en línea
Ver todos los comentarios