Los creacionales resolvieron el nacimiento de los objetos de PideYa; los estructurales, su anatomía. Queda la pregunta que cerraba el módulo anterior, la más dinámica de las tres: con los objetos ya creados y bien conectados, ¿cómo colaboran en ejecución? ¿Quién avisa a quién cuando un pedido cambia de estado? ¿Cómo se deshace una acción del panel del restaurante? ¿Dónde vive el algoritmo que decide qué repartidor lleva cada pedido? Los patrones de comportamiento responden a esto: reparten responsabilidades entre objetos y organizan su comunicación sin acoplarlos. Son la familia más numerosa del catálogo GoF —once patrones— y esta lección es su mapa: qué problema común atacan, quién es quién, y qué dolores concretos de PideYa está esperando cada uno.
Contenido
- El problema común: colaborar sin acoplarse
- Panorama de los once patrones de comportamiento
- Ámbito de clase y ámbito de objeto
- Síntomas en PideYa de que hace falta un patrón de comportamiento
- Cómo leeremos cada patrón en este módulo
- Ejercicios y conclusión
El problema común: colaborar sin acoplarse
Los creacionales respondían a ¿quién decide qué clase se instancia?; los estructurales, a ¿cómo se ensamblan las piezas?. Los patrones de comportamiento responden a dos preguntas entrelazadas:
- Asignación de responsabilidades: ¿qué objeto debe hacer cada cosa? ¿Dónde vive un algoritmo, quién guarda un estado, quién decide una transición?
- Comunicación: ¿cómo se hablan los objetos entre sí para completar una tarea que ninguno puede hacer solo?
Y el enemigo vuelve a ser el de siempre con una tercera cara: el acoplamiento, esta vez en las conversaciones. En el módulo 2 el acoplamiento se colaba por el new; en el 3, por las conexiones estructurales; aquí se cuela por las llamadas:
- Un objeto que, para hacer su trabajo, llama directamente a todos los interesados en él (¿te suena
Pedido.cambiarEstado(...)de la primera lección del curso? Este módulo salda esa deuda). - Un algoritmo cableado dentro de la clase que lo usa, imposible de cambiar sin tocarla.
- Una maraña de condicionales (
switchsobre estados,ifsobre tipos) que se repite por todo el código y crece con cada caso nuevo. - Objetos que se conocen todos con todos para coordinarse: una malla donde tocar uno arrastra a los demás.
- Peticiones que solo existen como llamadas efímeras: no se pueden encolar, deshacer, registrar ni reenviar.
La estrategia de la familia es siempre la misma, y ya la conoces de los principios del módulo 1: reificar — convertir en objeto lo que antes era código suelto. Un algoritmo se vuelve un objeto (Strategy), una petición se vuelve un objeto (Command), un estado se vuelve un objeto (State), una foto del pasado se vuelve un objeto (Memento), un recorrido se vuelve un objeto (Iterator). Una vez que algo es un objeto, se puede intercambiar, inyectar, encolar, guardar y probar. Es "programa contra interfaces" y "composición sobre herencia" aplicados a la conducta.
Panorama de los once patrones de comportamiento
La foto completa del módulo, cada patrón en una línea. No la memorices ahora: volveremos a ella, ampliada y con careos, en la comparativa final.
| Patrón | Intención en una línea |
|---|---|
| Chain of Responsibility | Pasar una petición por una cadena de manejadores hasta que alguno la atienda |
| Command | Encapsular una petición como objeto: encolarla, registrarla, deshacerla |
| Interpreter | Definir la gramática de un mini-lenguaje y un intérprete que evalúa sus frases |
| Iterator | Recorrer los elementos de una colección sin exponer su estructura interna |
| Mediator | Centralizar en un objeto las interacciones muchos-a-muchos entre colegas |
| Memento | Capturar el estado de un objeto para restaurarlo después, sin romper su encapsulación |
| Observer | Suscripción uno-a-muchos: cuando el sujeto cambia, todos sus observadores se enteran |
| State | Un objeto cuyo comportamiento cambia con su estado interno, sin condicionales gigantes |
| Strategy | Familia de algoritmos intercambiables, encapsulados tras una interfaz común |
| Template Method | Esqueleto de un algoritmo en una clase base con pasos que redefinen las subclases |
| Visitor | Añadir operaciones nuevas a una jerarquía estable de objetos sin modificarla |
Once son muchos, así que conviene agruparlos mentalmente por la conversación que organizan:
- Encapsular lo variable: Strategy (un algoritmo), State (un comportamiento dependiente del estado), Command (una petición), Template Method (pasos de un algoritmo), Interpreter (frases de un lenguaje).
- Comunicar sin acoplar: Observer (uno avisa a muchos que no conoce), Mediator (muchos hablan a través de uno), Chain of Responsibility (la petición busca quién la atienda).
- Trabajar sobre estructuras: Iterator (recorrerlas), Visitor (operar sobre ellas), Memento (fotografiarlas y restaurarlas).
Ámbito de clase y ámbito de objeto
Como en las familias anteriores, cada patrón tiene un ámbito: de clase si la colaboración se fija con herencia al compilar, o de objeto si se establece con composición en ejecución. La cuenta aquí es casi tan rotunda como en los estructurales: nueve de los once son de ámbito de objeto. Los dos de ámbito de clase son:
- Template Method: el esqueleto del algoritmo vive en la superclase y las subclases redefinen pasos heredando. Es el patrón de herencia por excelencia.
- Interpreter: la gramática se plasma en una jerarquía de clases (una clase por regla), fijada al compilar.
Los otros nueve componen: el contexto contiene una estrategia, el sujeto contiene observadores, el invocador contiene comandos... La pareja Template Method / Strategy es el careo perfecto de esta diferencia —mismo problema, uno lo resuelve heredando y otro componiendo— y lo veremos frente a frente en su lección.
Síntomas en PideYa de que hace falta un patrón de comportamiento
Como en los módulos anteriores: primero el síntoma, después el patrón. Todos estos dolores existen hoy en PideYa; cada uno tiene su lección:
| Síntoma en PideYa | Olor de diseño | Patrón que lo trata |
|---|---|---|
Un pedido entrante debe pasar controles (fraude, stock, zona de reparto, importe mínimo) y hoy son un método kilométrico de if anidados |
Validaciones en serie cableadas en un solo bloque, imposibles de reordenar o reutilizar | Chain of Responsibility |
| El panel del restaurante necesita "deshacer" (aceptar, cancelar, marcar en preparación...) y una cola de operaciones pendientes, pero cada acción es solo una llamada a método que se esfuma | Peticiones efímeras que no se pueden encolar, registrar ni revertir | Command |
| Marketing quiere escribir reglas de promoción ("total > 30 Y dia == VIERNES") sin desplegar código | Reglas de negocio expresadas como texto que alguien tiene que evaluar | Interpreter |
| Recorrer la carta Composite obliga a cada cliente a saber que hay secciones dentro de secciones | Estructura interna expuesta a todo el que quiere recorrerla | Iterator |
| Pedidos listos, repartidores y cocina se llaman entre sí para coordinarse: cada clase conoce a todas las demás | Acoplamiento en malla muchos-a-muchos | Mediator |
| El cliente edita su carrito y quiere "deshacer" sin que el carrito exponga sus tripas | Necesidad de guardar y restaurar estado sin romper encapsulación | Memento |
Pedido.cambiarEstado(...) crea con new los servicios de push, SMS y estadísticas — el dolor de la lección 01-01, aún sin resolver |
El sujeto conoce y llama a todos sus interesados | Observer |
Qué puede hacerse con un pedido depende de si está creado, pagado, en reparto...; el código es un switch sobre el estado repetido en cada método |
Comportamiento por estado disperso en condicionales duplicados | State |
| Los gastos de envío se calculan de tres maneras (distancia, tarifa plana, gratis por promoción) elegidas en ejecución | Algoritmos alternativos cableados con condicionales en el cliente | Strategy |
| Los informes de cierre diario repiten el mismo flujo (cargar → agregar → formatear → distribuir) con pasos distintos según el formato | Algoritmo duplicado en variantes que solo difieren en algunos pasos | Template Method |
Exportar la carta a JSON, calcular alérgenos y auditar precios amenazan con llenar Plato y SeccionCarta de métodos ajenos a su responsabilidad |
Operaciones nuevas que obligan a modificar una jerarquía estable | Visitor |
Cómo leeremos cada patrón en este módulo
Las once lecciones de patrón siguen el esqueleto de los módulos anteriores, para que compararlos sea fácil:
- El problema en PideYa, con el código del primer intento (el malo).
- Estructura: intención GoF y
classDiagrammermaid con los roles, como en la lección de UML. En esta familia añadiremos a menudosequenceDiagram, porque lo que importa es la conversación en el tiempo, no solo la foto estática. - Implementación Java completa, explicada paso a paso.
- Variantes relevantes de cada patrón.
- Cuándo usarlo y cuándo no, con la honestidad de costes habitual.
- Relación con otros patrones: solo menciones con enlace.
- Errores comunes, ejercicios con solución y conclusión.
Y seguimos construyendo sobre lo construido: la carta Composite del módulo 3 será recorrida por Iterator y visitada por Visitor; el Pedido.Builder del módulo 2 fabricará los pedidos que Observer vigila y State gobierna; los Notificador decorados del módulo 3 serán los receptores finales de las notificaciones de Observer; la FachadaCheckout invocará la cadena de validación de Chain of Responsibility. Un solo sistema, muchas conversaciones.
Ejercicios
Ejercicio 1: casar síntoma y patrón
Para cada situación nueva de PideYa, di qué patrón de comportamiento de la tabla parece apuntar (basta casar el síntoma con la intención de una línea):
- Cuando cambia el precio de un plato, deben enterarse el buscador, la caché del catálogo y el histórico de precios — y mañana quizá alguien más.
- El soporte quiere que una reclamación pase primero por el bot, luego por un agente, luego por un supervisor, y que cada nivel la resuelva o la escale.
- Queremos probar dos formas de ordenar los restaurantes en la home (por valoración, por cercanía) y elegirla por configuración.
- Al pulsar "guardar borrador" de una carta en edición, el restaurante quiere poder volver más tarde exactamente a ese punto.
Ejercicio 2: reificar
Este módulo repite un truco: convertir en objeto algo que antes era código suelto. Indica qué cosa se convierte en objeto en cada uno de estos patrones: Strategy, Command, Memento, Iterator, State.
Soluciones
Solución 1:
- Observer: un cambio, muchos interesados desconocidos y variables.
- Chain of Responsibility: la petición recorre manejadores hasta que uno la atiende (o la escala).
- Strategy: algoritmos alternativos e intercambiables tras una interfaz común.
- Memento: capturar el estado para restaurarlo después sin exponer las tripas del objeto.
Solución 2: Strategy reifica un algoritmo; Command, una petición (una llamada con sus argumentos); Memento, una instantánea de estado; Iterator, un recorrido (la posición y la lógica de avance); State, un estado y su comportamiento asociado.
Conclusión
Ya tienes el mapa de la familia más numerosa del catálogo: once patrones que reparten responsabilidades y organizan la comunicación entre objetos sin acoplarlos, casi todos mediante composición, y casi todos aplicando el mismo truco — reificar la conducta para poder intercambiarla, encolarla, guardarla o repartirla. Sabes qué dolor de PideYa espera a cada uno, incluido el más antiguo del curso: aquel cambiarEstado de la primera lección que lleva tres módulos esperando a Observer.
Pero empezamos por la puerta de entrada del negocio: cada pedido que llega a PideYa debe superar una carrera de obstáculos —¿es fraude?, ¿hay stock?, ¿repartimos en esa zona?, ¿llega al importe mínimo?— y hoy esa carrera es un método monolítico que nadie quiere tocar. Vamos a convertirla en una cadena de eslabones independientes y recombinables. Nos vemos en Chain of Responsibility.
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
- Principios de Diseño: SOLID y Otros Fundamentos
- UML Esencial para Entender Patrones
- 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
- Comparativa y Elección de Patrones Creacionales
Módulo 3: Patrones Estructurales
- Introducción a los Patrones Estructurales
- Adapter
- Bridge
- Composite
- Decorator
- Facade
- Flyweight
- Proxy
- Comparativa y Elección de 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
- Comparativa y Elección de Patrones de Comportamiento
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
- Antipatrones: Cuándo los Patrones se Vuelven un Problema
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 Concurrencia
- Patrones de Diseño en Desarrollo Ágil
