¿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
