¿Qué son los Patrones de Comportamiento?
Los patrones de comportamiento son soluciones reutilizables que se enfocan en la interacción y responsabilidad entre objetos. Estos patrones ayudan a definir cómo los objetos se comunican y colaboran entre sí, promoviendo la flexibilidad y la reutilización del código.
Características Clave de los Patrones de Comportamiento
- Interacción entre Objetos: Definen cómo los objetos se comunican y colaboran para realizar tareas complejas.
- Desacoplamiento: Promueven el desacoplamiento entre los objetos, permitiendo que los cambios en uno no afecten a los demás.
- Flexibilidad: Facilitan la adición de nuevas funcionalidades sin modificar el código existente.
- Reutilización: Fomentan la reutilización de código al proporcionar soluciones probadas y optimizadas.
Clasificación de los Patrones de Comportamiento
Los patrones de comportamiento se pueden clasificar en dos categorías principales:
- Patrones de Comportamiento de Clase: Se enfocan en la relación entre clases y sus subclases. Utilizan la herencia para distribuir el comportamiento entre las clases.
- Patrones de Comportamiento de Objeto: Se enfocan en la relación entre objetos. Utilizan la composición de objetos en lugar de la herencia.
Ejemplos de Patrones de Comportamiento
A continuación, se presentan algunos de los patrones de comportamiento más comunes:
- Chain of Responsibility: Permite que varios objetos tengan la oportunidad de manejar una solicitud, pasando la solicitud a lo largo de una cadena de manejadores.
- Command: Encapsula una solicitud como un objeto, permitiendo parametrizar a los clientes con diferentes solicitudes, colas o registros de solicitudes.
- Interpreter: Define una representación gramatical para un lenguaje y un intérprete que usa la representación para interpretar sentencias en el lenguaje.
- Iterator: Proporciona una forma de acceder secuencialmente a los elementos de un objeto agregado sin exponer su representación subyacente.
- Mediator: Define un objeto que encapsula cómo un conjunto de objetos interactúan.
- Memento: Permite capturar y externalizar el estado interno de un objeto sin violar la encapsulación, para que el objeto pueda ser restaurado a este estado más tarde.
- Observer: Define una dependencia de uno a muchos entre objetos, de manera que cuando un objeto cambia de estado, todos sus dependientes son notificados y actualizados automáticamente.
- State: Permite a un objeto alterar su comportamiento cuando su estado interno cambia.
- Strategy: Define una familia de algoritmos, encapsula cada uno y los hace intercambiables.
- Template Method: Define el esqueleto de un algoritmo en una operación, diferiendo algunos pasos a las subclases.
- Visitor: Representa una operación a realizar en los elementos de una estructura de objetos.
Ventajas y Desventajas de los Patrones de Comportamiento
Ventajas
- Modularidad: Facilitan la creación de sistemas modulares y mantenibles.
- Reutilización: Promueven la reutilización de código al proporcionar soluciones probadas.
- Flexibilidad: Permiten agregar nuevas funcionalidades sin modificar el código existente.
- Desacoplamiento: Reducen la dependencia entre objetos, lo que facilita el mantenimiento y la evolución del sistema.
Desventajas
- Complejidad: Pueden aumentar la complejidad del sistema debido a la introducción de múltiples objetos y relaciones.
- Sobrecarga de Rendimiento: En algunos casos, la implementación de estos patrones puede introducir una sobrecarga de rendimiento debido a la creación de objetos adicionales y la gestión de la comunicación entre ellos.
Ejemplo Práctico: Patrón Observer
Descripción
El patrón Observer define una relación de dependencia uno-a-muchos entre objetos, de manera que cuando un objeto cambia de estado, todos sus dependientes son notificados y actualizados automáticamente.
Implementación en Python
class Subject:
def __init__(self):
self._observers = []
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
class ConcreteSubject(Subject):
def __init__(self, state):
super().__init__()
self._state = state
@property
def state(self):
return self._state
@state.setter
def state(self, value):
self._state = value
self.notify()
class Observer:
def update(self, subject):
pass
class ConcreteObserver(Observer):
def update(self, subject):
print(f"Observer: Reacted to the state change to {subject.state}")
# Uso del patrón Observer
subject = ConcreteSubject(0)
observer1 = ConcreteObserver()
observer2 = ConcreteObserver()
subject.attach(observer1)
subject.attach(observer2)
subject.state = 10 # Notifica a los observadoresExplicación del Código
- Subject: Clase base que mantiene una lista de observadores y proporciona métodos para adjuntar, desadjuntar y notificar a los observadores.
- ConcreteSubject: Extiende la clase
Subjecty mantiene el estado que se observa. Cuando el estado cambia, notifica a todos los observadores. - Observer: Clase base para los observadores, define el método
updateque se llama cuando elSubjectcambia de estado. - ConcreteObserver: Implementa el método
updatepara reaccionar a los cambios en elSubject.
Ejercicio Práctico
Implementa el patrón Observer para un sistema de notificaciones de temperatura. Crea una clase TemperatureSensor que actúe como el Subject y una clase TemperatureDisplay que actúe como el Observer. El TemperatureSensor debe notificar a todos los TemperatureDisplay cuando la temperatura cambie.
Solución
class TemperatureSensor:
def __init__(self):
self._observers = []
self._temperature = 0
def attach(self, observer):
self._observers.append(observer)
def detach(self, observer):
self._observers.remove(observer)
def notify(self):
for observer in self._observers:
observer.update(self)
@property
def temperature(self):
return self._temperature
@temperature.setter
def temperature(self, value):
self._temperature = value
self.notify()
class TemperatureDisplay:
def update(self, sensor):
print(f"Temperature Display: The current temperature is {sensor.temperature}°C")
# Uso del patrón Observer
sensor = TemperatureSensor()
display1 = TemperatureDisplay()
display2 = TemperatureDisplay()
sensor.attach(display1)
sensor.attach(display2)
sensor.temperature = 25 # Notifica a los displays
sensor.temperature = 30 # Notifica a los displaysExplicación del Ejercicio
- TemperatureSensor: Actúa como el
Subject, mantiene una lista de observadores y notifica a los observadores cuando la temperatura cambia. - TemperatureDisplay: Actúa como el
Observer, actualiza la visualización de la temperatura cuando elTemperatureSensornotifica un cambio.
Conclusión
En esta sección, hemos introducido los patrones de comportamiento, destacando su importancia en la interacción y responsabilidad entre objetos. Hemos explorado sus características, ventajas y desventajas, y proporcionado un ejemplo práctico del patrón Observer. En las siguientes secciones, profundizaremos en cada uno de los patrones de comportamiento, 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
