Patrones de diseño en Java

Guía completa de patrones de diseño para desarrolladores Java

Patrones Creacionales

Estos patrones se centran en la creación de objetos, abstrayendo el proceso de instanciación.

Singleton

Asegura que una clase tenga una única instancia y proporciona un punto global de acceso a ella.

Factory Method

Define una interfaz para crear un objeto, pero permite a las subclases decidir qué clase instanciar.

Patrón Singleton

public class ConexionBD { private static ConexionBD instancia; private ConexionBD() {} public static ConexionBD getInstancia() { if (instancia == null) { instancia = new ConexionBD(); } return instancia; } }

Única instancia

Garantiza que solo exista una instancia de la clase en toda la aplicación

Acceso global

Proporciona un punto de acceso global a la instancia

Constructor privado

Evita la creación de nuevas instancias desde fuera de la clase

Patrón Factory Method

public interface Transporte { void entregar(); } public class Camion implements Transporte { public void entregar() { System.out.println("Entrega en camión."); } } public class TransporteFactory { public static Transporte crearTransporte(String tipo) { if ("camion".equals(tipo)) return new Camion(); throw new IllegalArgumentException("Tipo no soportado."); } }

Definir interfaz

Crear una interfaz común para todos los objetos

Implementar clases

Desarrollar las clases concretas que implementan la interfaz

Crear factory

Implementar el método factory que decide qué clase instanciar

Patrones Estructurales

Se enfocan en la composición de clases y objetos para formar estructuras más complejas.

Adapter

Permite que interfaces incompatibles trabajen juntas

Composite

Trata objetos individuales y compuestos de forma uniforme

Bridge

Separa una abstracción de su implementación

Decorator

Añade responsabilidades a objetos dinámicamente

2
3

Compatibilidad

Permite la interoperabilidad entre interfaces incompatibles

2

Integración

Facilita la integración de sistemas existentes

3

Reutilización

Permite reutilizar código existente sin modificarlo


Patrón Adapter

1

Dispositivo USB Incompatible

Nuestro sistema espera un dispositivo USB estándar, pero a veces nos encontramos con dispositivos que no cumplen con esa interfaz.

2

Adaptador al Rescate

El Patrón Adapter nos permite convertir un dispositivo incompatible, como una tarjeta SD, en uno que sí funcione con nuestro sistema.

3

Magia Oculta

El adaptador encapsula la lógica necesaria para hacer que la tarjeta SD se comporte como un dispositivo USB, ocultando los detalles de implementación.



Patrón Adapter

// Esta es la interfaz que espera nuestro sistema public interface DispositivoUSB { void conectarUSB(); } // Esta es una clase que representa una tarjeta SD, que no tiene conector USB public class TarjetaSD { public void insertar() { System.out.println("Tarjeta SD insertada."); } } // Este es el adaptador que convierte una tarjeta SD en un dispositivo USB public class AdaptadorSDaUSB implements DispositivoUSB { private TarjetaSD tarjeta; public AdaptadorSDaUSB(TarjetaSD tarjeta) { this.tarjeta = tarjeta; } @Override public void conectarUSB() { tarjeta.insertar(); // Adaptamos la interfaz } } // Simulación del uso public class Main { public static void main(String[] args) { TarjetaSD sd = new TarjetaSD(); DispositivoUSB adaptador = new AdaptadorSDaUSB(sd); adaptador.conectarUSB(); // El sistema cree que es un USB, pero es una SD adaptada } }

Patrón Composite

public interface Componente { void mostrar(); } public class Archivo implements Componente { private String nombre; public Archivo(String nombre) { this.nombre = nombre; } public void mostrar() { System.out.println("Archivo: " + nombre); } } public class Carpeta implements Componente { private String nombre; private List hijos = new ArrayList<>(); public Carpeta(String nombre) { this.nombre = nombre; } public void agregar(Componente c) { hijos.add(c); } public void mostrar() { System.out.println("Carpeta: " + nombre); for (Componente c : hijos) { c.mostrar(); } } }

Interfaz común

Define operaciones comunes para todos los componentes

Componentes simples

Implementan la interfaz para objetos individuales

Componentes compuestos

Contienen y gestionan componentes hijos

Patrón Composite

Uso ejemplo:


public class Main { public static void main(String[] args) { Carpeta raiz = new Carpeta("Documentos"); Carpeta fotos = new Carpeta("Fotos"); Carpeta trabajo = new Carpeta("Trabajo"); Archivo foto1 = new Archivo("vacaciones.jpg"); Archivo foto2 = new Archivo("cumpleaños.png"); Archivo doc1 = new Archivo("informe.docx"); fotos.agregar(foto1); fotos.agregar(foto2); trabajo.agregar(doc1); raiz.agregar(fotos); raiz.agregar(trabajo); raiz.mostrar(); } }

Salida:

Documentos ├── Fotos │ ├── vacaciones.jpg │ └── cumpleaños.png └── Trabajo └── informe.docx

Gracias al patrón Composite podemos tratar del mismo modo Archivos y Carpetas

Patrones de Comportamiento

Se ocupan de la comunicación entre objetos. Los patrones Observer y Strategy son ejemplos destacados que facilitan la interacción entre componentes de software.