¿Qué son los Patrones Estructurales?
Los patrones estructurales se centran en la composición de clases y objetos. Su objetivo principal es facilitar el diseño de estructuras complejas mediante la identificación de relaciones simples entre entidades. Estos patrones ayudan a garantizar que, al combinar objetos y clases, el sistema sea flexible y eficiente.
Características Clave de los Patrones Estructurales:
- Composición de Objetos: Facilitan la creación de estructuras complejas a partir de objetos más simples.
- Flexibilidad: Permiten que las estructuras sean fácilmente modificables y extensibles.
- Reutilización: Promueven la reutilización de componentes a través de la composición en lugar de la herencia.
Tipos de Patrones Estructurales
A continuación, se presentan los principales patrones estructurales que se estudiarán en este módulo:
- Adapter (Adaptador): Permite que clases con interfaces incompatibles trabajen juntas.
- Bridge (Puente): Desacopla una abstracción de su implementación, permitiendo que ambas evolucionen independientemente.
- Composite (Composición): Permite tratar objetos individuales y composiciones de objetos de manera uniforme.
- Decorator (Decorador): Añade responsabilidades adicionales a un objeto de manera dinámica.
- Facade (Fachada): Proporciona una interfaz simplificada a un conjunto de interfaces en un subsistema.
- Flyweight (Peso Ligero): Reduce el uso de memoria compartiendo tanto como sea posible con objetos similares.
- Proxy (Proxy): Proporciona un sustituto o marcador de posición para otro objeto para controlar el acceso a él.
Ventajas de los Patrones Estructurales
- Modularidad: Facilitan la creación de sistemas modulares donde los componentes pueden ser desarrollados y probados de manera independiente.
- Mantenibilidad: Simplifican la estructura del código, lo que facilita su mantenimiento y comprensión.
- Flexibilidad: Permiten que las estructuras de objetos sean más flexibles y adaptables a cambios futuros.
Desventajas de los Patrones Estructurales
- Complejidad: En algunos casos, pueden añadir complejidad adicional al sistema debido a la introducción de nuevas clases y objetos.
- Sobrecarga: Pueden introducir una sobrecarga en términos de rendimiento y memoria, especialmente si no se utilizan correctamente.
Ejemplo Práctico: Uso del Patrón Adapter
Problema:
Supongamos que tenemos una clase Cliente
que espera recibir datos de un servicio en un formato específico, pero el servicio actual proporciona los datos en un formato diferente.
Solución:
Utilizaremos el patrón Adapter para crear una clase adaptadora que convierta los datos del formato del servicio al formato esperado por la clase Cliente
.
Código de Ejemplo:
# Clase que proporciona datos en un formato específico class ServicioExistente: def obtener_datos(self): return {"nombre": "Juan", "edad": 30} # Clase Cliente que espera los datos en un formato diferente class Cliente: def __init__(self, datos): self.nombre = datos["nombre_completo"] self.edad = datos["años"] def mostrar_datos(self): print(f"Nombre: {self.nombre}, Edad: {self.edad}") # Adaptador que convierte los datos del formato del servicio al formato esperado por el Cliente class AdaptadorServicio: def __init__(self, servicio): self.servicio = servicio def obtener_datos(self): datos = self.servicio.obtener_datos() return { "nombre_completo": datos["nombre"], "años": datos["edad"] } # Uso del adaptador servicio = ServicioExistente() adaptador = AdaptadorServicio(servicio) datos_adaptados = adaptador.obtener_datos() cliente = Cliente(datos_adaptados) cliente.mostrar_datos()
Explicación del Código:
- ServicioExistente: Proporciona datos en un formato específico.
- Cliente: Espera recibir datos en un formato diferente.
- AdaptadorServicio: Actúa como un adaptador que convierte los datos del formato del servicio al formato esperado por el cliente.
- Uso del Adaptador: Creamos una instancia del servicio existente, la pasamos al adaptador y luego usamos los datos adaptados para crear una instancia del cliente.
Ejercicio Práctico
Ejercicio:
Crea un adaptador para una clase ServicioNuevo
que proporciona datos en el siguiente formato:
El adaptador debe convertir estos datos al formato esperado por la clase Cliente
.
Solución:
# Clase que proporciona datos en un formato diferente class ServicioNuevo: def obtener_datos(self): return {"first_name": "Juan", "years_old": 30} # Adaptador que convierte los datos del formato del nuevo servicio al formato esperado por el Cliente class AdaptadorNuevoServicio: def __init__(self, servicio): self.servicio = servicio def obtener_datos(self): datos = self.servicio.obtener_datos() return { "nombre_completo": datos["first_name"], "años": datos["years_old"] } # Uso del adaptador nuevo_servicio = ServicioNuevo() adaptador_nuevo = AdaptadorNuevoServicio(nuevo_servicio) datos_adaptados_nuevos = adaptador_nuevo.obtener_datos() cliente_nuevo = Cliente(datos_adaptados_nuevos) cliente_nuevo.mostrar_datos()
Explicación de la Solución:
- ServicioNuevo: Proporciona datos en un nuevo formato.
- AdaptadorNuevoServicio: Convierte los datos del nuevo formato al formato esperado por el cliente.
- Uso del Adaptador: Creamos una instancia del nuevo servicio, la pasamos al adaptador y luego usamos los datos adaptados para crear una instancia del cliente.
Conclusión
En esta sección, hemos introducido los patrones estructurales, destacando su importancia en la composición de clases y objetos para crear estructuras complejas y flexibles. Hemos explorado las ventajas y desventajas de estos patrones y proporcionado un ejemplo práctico del patrón Adapter. En las próximas lecciones, profundizaremos en cada uno de los patrones estructurales mencionados, proporcionando ejemplos detallados y ejercicios prácticos para reforzar el aprendizaje.
Curso de Patrones de Diseño de Software
Módulo 1: Introducción a los Patrones de Diseño
- ¿Qué son los Patrones de Diseño?
- Historia y Origen de los Patrones de Diseño
- Clasificación de los Patrones de Diseño
- Ventajas y Desventajas de Usar Patrones de Diseño
Módulo 2: Patrones Creacionales
- Introducción a los Patrones Creacionales
- Singleton
- Factory Method
- Abstract Factory
- Builder
- Prototype
Módulo 3: Patrones Estructurales
Módulo 4: Patrones de Comportamiento
- Introducción a los Patrones de Comportamiento
- Chain of Responsibility
- Command
- Interpreter
- Iterator
- Mediator
- Memento
- Observer
- State
- Strategy
- Template Method
- Visitor
Módulo 5: Aplicación de Patrones de Diseño
- Cómo Seleccionar el Patrón Adecuado
- Ejemplos Prácticos de Uso de Patrones
- Patrones de Diseño en Proyectos Reales
- Refactorización Usando Patrones de Diseño
Módulo 6: Patrones de Diseño Avanzados
- Patrones de Diseño en Arquitecturas Modernas
- Patrones de Diseño en Microservicios
- Patrones de Diseño en Sistemas Distribuidos
- Patrones de Diseño en Desarrollo Ágil