Skip to content

Clase 12 — Cierre de Patrones de Diseño y Orientación al Examen

Resumen Ejecutivo

Sesión de cierre del Tema 7 con tres bloques. Primero, repaso de los últimos patrones de comportamiento GoF: Cadena de Responsabilidad, Mediador, Observador y Estado, con ejemplos en JavaScript y discusión sobre combinaciones entre patrones. Segundo, revisión de los patrones de diseño de interfaz de usuario (catálogos de UI patterns), diferenciándolos explícitamente de los patrones de diseño de clases. Tercero, orientación detallada al examen: estructura, apartados, criterios de corrección, tipos de aplicación que pueden aparecer y consejos específicos sobre historias de usuario, planificación de sprints y estimación de tareas. ⚠️ EXAMEN: todo el bloque de orientación es material crítico para preparar el examen.


Conceptos Clave

  • Cadena de Responsabilidad: Patrón de comportamiento en el que una solicitud se pasa por una cadena de objetos hasta que uno la procesa. Desacopla emisor y receptor. ⚠️ EXAMEN
  • Diferencia Cadena de Responsabilidad vs Tuberías y Filtros: En Tuberías y Filtros la información se transforma secuencialmente en cada filtro; en Cadena de Responsabilidad la solicitud no se transforma, sino que se pasa hasta encontrar el objeto capaz de procesarla (la cadena puede no ejecutarse entera). ⚠️ EXAMEN
  • Mediador: Objeto central que centraliza y orquesta la comunicación entre muchos objetos con alto acoplamiento mutuo. Compatible con el patrón Observador (el mediador es el observador de todos los elementos). ⚠️ EXAMEN
  • Observador: Patrón sujeto/observador. Los sujetos notifican cambios de estado; los observadores se suscriben (attach) y desuscriben (detach). ⚠️ EXAMEN
  • Estado: El comportamiento de un objeto cambia según su estado interno. Se evitan grandes bloques switch/if extrayendo cada estado a una clase especializada. ⚠️ EXAMEN
  • Patrones de diseño de interfaz: Catálogos de soluciones recurrentes para problemas de UX/UI (carrusel, checklist, password strength indicator...). Son completamente distintos a los patrones GoF.
  • Estructura del examen: Pregunta teórica (3 puntos, elegir 1 de 2) + ejercicio de proyecto (7 puntos, 4 apartados relacionados con actividades 1 y 2).

Desarrollo del Temario

1. Patrón Cadena de Responsabilidad

Problema: el cliente no sabe qué objeto es capaz de procesar una solicitud. Si lo resuelve consultando directamente a cada receptor en secuencia, el código queda muy acoplado y es difícil de escalar.

Solución: definir una interfaz Handler con un método handle y un enlace al siguiente manejador. Cada manejador concreto procesa lo que puede y pasa el resto al siguiente.

// Clase base (en JS aproximamos clase abstracta)
class Handler {
    setNext(handler) {
        this.next = handler;
        return handler;
    }
    handle(request) {
        if (this.next) return this.next.handle(request);
        return null;
    }
}

// Manejador concreto
class EmailValidator extends Handler {
    handle(request) {
        if (!request.email || !request.email.includes('@')) {
            return 'Error: email inválido';
        }
        return super.handle(request); // pasa al siguiente
    }
}

class PasswordValidator extends Handler {
    handle(request) {
        if (!request.password || request.password.length < 6) {
            return 'Error: contraseña muy corta';
        }
        return super.handle(request);
    }
}

// Configurar la cadena
function validateForm(request) {
    const emailValidator = new EmailValidator();
    const passwordValidator = new PasswordValidator();
    emailValidator.setNext(passwordValidator);
    return emailValidator.handle(request);
}

Características clave: - El orden de la cadena lo define quien la construye, no las propias clases. - La cadena no siempre se recorre entera: se detiene cuando un manejador no puede pasar al siguiente o cuando hay un error. - Compatible con el patrón Builder para construir la cadena. - Compatible con el patrón Composite: en jerarquías de objetos, el padre transmite solicitudes a los hijos.

Diferencia con Tuberías y Filtros: ⚠️ EXAMEN

Cadena de Responsabilidad Tuberías y Filtros
Naturaleza Solicitud/evento que busca receptor Dato que sufre transformaciones
Ejecución Puede detenerse antes de acabar Siempre recorre todos los filtros
Transformación No transforma (busca quién procesa) Transforma en cada etapa
Nivel Patrón de diseño detallado Patrón arquitectónico

Ejemplo práctico: abrir un fichero en el explorador del SO. El sistema pasa la ruta por una cadena de manejadores (por extensión, por cabecera binaria...) hasta encontrar el programa capaz de abrirlo.

Beneficios: mejor cohesión (cada clase valida solo una cosa), menor acoplamiento (emisor no conoce al receptor final), fácil de extender sin modificar clases existentes.


2. Patrón Mediador

Problema: muchos objetos se comunican entre sí, generando una maraña de acoplamientos. Ejemplo: formulario con muchos campos donde la habilitación de un botón depende de varios campos.

Solución: un objeto central (el Mediador) conoce a todos los colaboradores y centraliza la lógica de coordinación. Los colaboradores ya no se conocen entre sí.

Combinación con Observador: ⚠️ EXAMEN El mediador es el observador de todos los objetos del formulario. Cada vez que un campo cambia (evento keyChange), notifica al mediador, que actualiza el estado de la interfaz. Así: - Solo el mediador tiene lógica de coordinación. - Si la lógica se complica, se puede refactorizar solo el mediador. - Los colaboradores quedan simples y desacoplados entre sí.

Ventaja e inconveniente: el mediador puede convertirse en un objeto muy complejo. Sin embargo, esa complejidad está concentrada en un único lugar, lo que es preferible a tenerla dispersa por toda la aplicación.

Relación con arquitectura de microservicios: los orquestadores de microservicios y los orquestadores de agentes de IA son conceptualmente similares al mediador: un componente central que coordina la colaboración entre muchos servicios/agentes.

classDiagram
    class Mediador {
        -colaboradores: List
        +notify(origen, evento)
    }
    class Campo1 {
        -mediador: Mediador
        +onChange()
    }
    class Campo2 {
        -mediador: Mediador
        +onChange()
    }
    class Boton {
        +setEnabled(bool)
    }
    Mediador o-- Campo1
    Mediador o-- Campo2
    Mediador o-- Boton

3. Patrón Observador

Patrón sujeto-observador para notificar cambios de estado a múltiples objetos.

Roles: - Sujeto: produce cambios de estado. Implementa attach(observer), detach(observer) y notify(). - Observador: se suscribe al sujeto y recibe notificaciones mediante update().

Funcionamiento: 1. Los observadores hacen attach(self) en el sujeto. 2. Cuando el sujeto cambia, llama a notify() que recorre su lista e invoca update() en cada observador. 3. El observador puede pedir el nuevo estado con getState().

Compatibilidad: un observador puede establecer, a su vez, una cadena de responsabilidad con los otros observadores.

Regla mnemotécnica: el observador es "la vieja del visillo": está detrás de su visillo observando a los sujetos que pasan.


4. Patrón Estado

Problema: el comportamiento de un objeto depende de combinaciones de atributos internos. El resultado son grandes bloques switch o anidaciones de if que generan código espagueti.

Solución: extraer el código asociado a cada estado a una clase especializada. El objeto contexto delega la operación en el objeto de estado actual. Si el estado cambia (p. ej. el objeto "bebe una poción envenenada"), el contexto instancia el objeto de estado nuevo.

Ejemplo conceptual (videojuego):

Elfo (contexto)
    estado = ElfoNormal | ElfoMalito | ElfoNigromante
    beber(poción)  → delega en estado.beber(poción)
                   → estado cambia según resultado

Beneficio: cada clase de estado es pequeña, cohesionada y fácil de mantener. Añadir un nuevo estado no modifica los existentes.


5. Patrones de Diseño de Interfaz de Usuario

Diferencia crítica con los patrones GoF: ⚠️ EXAMEN Los patrones de UI (catálogos como ui-patterns.com) son soluciones recurrentes a problemas de diseño visual e interacción con el usuario. No tienen nada que ver con diagramas de clases, interfaces ni herencia.

Categorías habituales: - Obtener información del usuario (formularios, checkboxes, password strength) - Navegación (carrusel, breadcrumb, pagination) - Feedback al usuario (progress bar, notificaciones, mensajes de error) - Trabajando con datos (tablas, búsqueda, filtros)

Error frecuente en los trabajos: mezclar ambos tipos de patrones en el mismo apartado del trabajo o confundir el observador con un patrón de interfaz. En la actividad: el último apartado pide patrones de UI, no patrones GoF.


6. Orientación al Examen ⚠️ EXAMEN

6.1 Estructura del examen

Parte Descripción Puntos
Pregunta teórica Elegir 1 de 2 preguntas sobre temario 3
Ejercicio de proyecto 4 apartados sobre una aplicación ficticia 7

Materiales permitidos: calculadora básica (útil para sumas de horas en planificación). En examen online: folios en blanco para dibujar, fotografiados y subidos.

Los diagramas deben hacerse a mano (no se permite draw.io ni herramientas de dibujo). Los enunciados estarán como adjunto en la plataforma del examen.

6.2 Pregunta teórica

  • Dos opciones a elegir; pueden ser del mismo tema o de temas distintos.
  • Una página de espacio.
  • Hay un documento de orientaciones en el aula (sección Documentación) con lo más importante de cada tema.
  • Patrones que hay que conocer sí o sí según el profesor: Web Queue Worker, CQRS (Command and Query Responsibility Segregation), y los patrones GoF vistos en clase.
  • Metodologías ágiles (Scrum): roles, artefactos, ceremonias. Saber explicar el esquema general.

6.3 Ejercicio de proyecto (7 puntos)

La aplicación será inventada por el profesor en el momento (aplicación móvil, web o de escritorio). Puede ser cualquier cosa: app de aparcamientos, recetas de cocina, traducción instantánea con cámara, resultados de petanca de Zamora... El tipo de plataforma (móvil/web/escritorio) condiciona qué patrones tienen sentido.

Los 4 apartados:

Apartado 1 — Historias de usuario - Redactar historias con el formato: Como <rol>, necesito <funcionalidad> para <objetivo>. - ⚠️ EXAMEN: no incluir historias triviales ni genéricas (cambiar foto de perfil, registrarse...). Deben ser específicas del dominio de la aplicación propuesta. - Las historias triviales o genéricas no puntúan.

Apartado 2 — Planificación del sprint - Seleccionar 5 historias para la pila de producto y planificar un sprint con 3 de ellas. - Descomponer las 3 en tareas con estimaciones de horas. - Definir el equipo (número de personas, horas disponibles). - La planificación debe ser coherente con la capacidad real del equipo. ⚠️ EXAMEN - No dejar márgenes genéricos masivos; si hay incertidumbre, modelarla a nivel de tarea concreta. - Las historias seleccionadas deben respetar las prioridades del Product Owner, no las preferencias del alumno. - No se pide Kanban ni burndown chart.

Criterios de corrección de la planificación: - Las horas de las tareas del sprint deben sumar aproximadamente lo que el equipo puede hacer. - Justificar el tiempo dedicado a ceremonias (daily, revisión, retrospectiva) como tareas concretas, no como porcentajes de holgura. - Si se planifica por debajo de la capacidad, tener una historia en "recámara" lista para añadir si sobra tiempo.

Apartado 3 — Diseño arquitectónico general - Diagrama de arquitectura general aplicando 3 patrones arquitectónicos. - Por cada patrón: tabla con nombre, problema que resuelve y diagrama. - El diagrama debe estar dibujado por el alumno, no copiado de ninguna fuente. - El tipo de plataforma importa: no tiene sentido un patrón de microservicios en una app de escritorio simple sin justificación.

Apartado 4 — Diseño detallado con patrones GoF - Identificar 2 problemas de comportamiento/estructurales del software. - Por cada problema: indicar el patrón GoF que lo resuelve y dibujar el diagrama de clases. - Para el Singleton hay que representar los elementos específicos del patrón. - No hay que escribir código, pero sí dibujar el diagrama correctamente.

6.4 Errores frecuentes que penalizan

  • Historias de usuario triviales o genéricas (no específicas del dominio).
  • Planificación con capacidad del equipo muy por debajo de lo posible (márgenes del 40-50%).
  • Mezclar patrones GoF con patrones de UI en el mismo apartado.
  • Copiar diagramas de internet o de la presentación del profesor.
  • Seleccionar historias de prioridad baja sin justificar por qué se incluyeron.
  • Diagramas de arquitectura generados por IA con errores evidentes (grafos ASCII sin sentido, flechas aleatorias).
  • CDN descrito como servidor de aplicaciones (error conceptual grave).

Preguntas de Autoevaluación

  1. ⚠️ EXAMEN: Explica la diferencia entre Cadena de Responsabilidad y el patrón de Tuberías y Filtros. Da un ejemplo de cuándo usarías cada uno.
  2. ¿Por qué el Mediador puede combinarse con el Observador? ¿Cuál sería el rol de cada uno en un formulario con muchos campos interdependientes?
  3. ¿Cuáles son las tres responsabilidades de la interfaz del Sujeto en el patrón Observador?
  4. En el patrón Estado, ¿qué ventaja tiene crear clases especializadas por estado frente a usar un gran bloque switch?
  5. ⚠️ EXAMEN: ¿Qué diferencia hay entre un patrón de diseño GoF y un patrón de diseño de interfaz de usuario? Da un ejemplo de cada tipo.
  6. Cómo deben redactarse las historias de usuario en el examen. ¿Qué tipo de historias NO puntúan?
  7. ⚠️ EXAMEN: ¿Por qué no tiene sentido dejar un margen genérico del 20% en la planificación del sprint? ¿Dónde debe modelarse la incertidumbre?
  8. ¿Quién decide qué historias entran en el sprint y con qué prioridad? ¿Puede el alumno/desarrollador cambiar ese orden por su cuenta?
  9. ¿Qué materiales están permitidos en el examen y para qué sirve la calculadora?
  10. En el apartado de diseño detallado, ¿qué dos cosas hay que incluir por cada patrón GoF identificado?