fedorthinks

Curso exprés · No. 04

La mayoría ya los reinventaste a mano. Un patrón es solo el nombre — para que un equipo pueda decir en una palabra lo que llevaría un párrafo, y reconocer la jugada antes de hacerla mal.

20 patrones · un diagrama para cada uno · hoja de referencia al final

§ 01

Un patrón de diseño es una solución con nombre y reutilizable a un problema que aparece una y otra vez en el código. Es vocabulario, no una librería — no lo instalás, lo reconocés.

Design Pattern — el nombre de una jugada que ya hacés

Los futbolistas no inventan «la pared» en medio del partido. Tiene un nombre, y decir el nombre es más rápido que describir toda la jugada.

Un patrón de diseño es una jugada que los desarrolladores competentes reinventan a mano de todos modos. Ponerle nombre convierte un párrafo de explicación en una palabra que todo el equipo comparte. Cuando alguien dice «envolvelo en un Decorator», todos ven la forma al instante — y ese es todo el sentido de un patrón: un vocabulario compartido para jugadas que harías igual.

ConceptDesign Pattern· patrón de diseño
Qué es
Una solución con nombre a un problema que se repite en el código.
Qué no es
No es una librería: no se instala, se reconoce y se escribe.
Escala

Vive dentro del código de un módulo — a diferencia de los patrones de arquitectura, que deciden el plano de todo el sistema.

Para qué
Lenguaje compartido: una palabra en vez de un párrafo.

Gang of Four — los patrones se descubren, no se inventan

Nadie inventó el arco. Los constructores seguían encontrando que era la forma más fuerte de salvar un vano — así que le pusieron un nombre.

La Banda de los Cuatro (Gang of Four, GoF) son los cuatro autores del libro Design Patterns. No diseñaron 23 trucos ingeniosos; catalogaron soluciones que seguían reapareciendo en el buen código. Así que un patrón no es un objetivo que cumplir — es una forma a la que llegás naturalmente cuando el problema lo pide. Si estás forzando uno, probablemente todavía no tenés el problema.

El mapa: tres familias, tres preguntas

Una cocina tiene herramientas para tres tareas: preparar la comida, emplatarla y servirla. Los patrones se dividen igual.

Los patrones de creación son sobre cómo nacen los objetos — quién los construye, y cómo. Los patrones estructurales son sobre cómo encajan los objetos en formas más grandes. Los patrones de comportamiento son sobre cómo hablan los objetos y reparten responsabilidad. Casi todo patrón clásico es una de esas tres respuestas.

Creationalhow objects are bornFactoryAbstract FactoryBuilderSingletonPrototypeStructuralhow objects fit togetherAdapterDecoratorFacadeProxyCompositeBehaviouralhow objects talk and share workStrategyObserverCommandChain of ResponsibilityStateIteratorTemplate MethodMediatorVisitorMemento
Tres familias y los 20 patrones del curso — los capítulos 2–5 las siguen.

Indirection — un patrón que no necesitás es solo complejidad

Una navaja suiza en el bolsillo es práctica. Atornillar las veinte herramientas a la puerta de tu casa, no.

Todo patrón agrega indirección — una capa entre vos y la cosa. Vale la pena cuando compra flexibilidad que de verdad vas a usar, y es puro coste cuando no. El error común no es ignorar los patrones; es echar mano de uno antes de que exista el problema.

Cómo leer cada patrón

Un pasaporte: todos tienen los mismos campos, así que es fácil compararlos.

Cada patrón de aquí en adelante tiene las mismas partes: su nombre en inglés (ese es el término — recordalo), una imagen de la vida cotidiana, un diagrama y una ficha con campos: problema (qué duele), idea (cómo lo resuelve), ejemplo, coste (qué pagás), cuándo usarlo y patrones relacionados. Al final hay una hoja de referencia con todos los nombres en una página.

Un patrón es un atajo para una conversación. Usalo para que te entiendan, no para parecer ingenioso.

§ 02

Cómo cobran vida los objetos — sin esparcir new por todas partes ni soldar tu código a clases concretas.

Factory — pedí la cosa por su nombre, no por su receta

Una cafetera: apretás «latte» y te sale uno. No molés, no espumás, no servís vos — y no necesitás saber cómo se hace.

Una Factory te entrega un objeto sin que llames directamente a su constructor, así que el código que llama nunca depende de la clase concreta. Solo conoce la interfaz. Compra la libertad de cambiar lo que se construye sin tocar a quien lo pidió.

Clientasks by namecreate("stripe")Factorypicks the classStripeProviderPayPalProviderFakeProviderthe caller knows only the PaymentProvider interface — never the concrete class
El cliente pide por nombre; la fábrica elige la clase; el cliente solo ve la interfaz PaymentProvider.
PatternFactory· Factory Method, fábrica
Problema

new StripeProvider() está esparcido por el código — soldado a una clase.

Idea
Pedile el objeto a una fábrica; ella decide qué clase construir.
Ejemplo

createPaymentProvider("stripe") devuelve un PaymentProvider. Pasarse a PayPal significa cambiar la fábrica, no cada lugar de llamada.

Coste

Una capa extra. Una fábrica que construye exactamente una cosa es un mal olor.

Cuándo usarlo
Hay varias implementaciones, o las habrá.
Relaciones

Abstract Factory — la misma idea para una familia entera de objetos.

Abstract Factory — toda una familia que combina, de una vez

Comprar un juego de muebles — «Victoriano» o «Moderno» — donde cada pieza llega en el mismo estilo, sin sillas desparejas.

Cuando los objetos deben venir en familias coherentes, una Abstract Factory construye el conjunto entero de una vez para que las partes encajen. Potente — pero es maquinaria pesada, y vale la pena solo cuando las familias son reales.

macOS factoryButtonmacMenumacDialogmacWindows factoryButtonwinMenuwinDialogwinpick ONE familyone factory = one matching set; never a mac Button next to a Windows Menu
Una fábrica, un conjunto que combina: botón, menú y diálogo del mismo estilo.
PatternAbstract Factory· abstract factory, fábrica abstracta
Problema
Los objetos deben combinar entre sí, y es fácil mezclarlos.
Idea
Una fábrica produce el conjunto entero en un solo estilo.
Ejemplo

Un kit de UI que produce botones, menús y diálogos a juego para macOS o para Windows desde una sola fábrica.

Coste
Maquinaria pesada: muchas interfaces y clases.
Cuándo usarlo
Solo cuando las familias son reales, y hay más de una.
Relaciones

Se construye a partir de Factory. «Una fábrica abstracta para un solo producto» es sobreingeniería clásica.

Builder — armá un objeto complejo paso a paso

Pedir una hamburguesa a medida — pan, carne, sin cebolla, queso extra — una elección a la vez, y al final «listo».

Cuando un objeto tiene muchas partes opcionales, un Builder te deja fijarlas de a una en vez de usar un constructor monstruoso con doce argumentos. Al final llamás a build() y obtenés el objeto terminado. Cambia un constructor desconcertante por una cadena legible.

set one optional part at a timeselect(name)where(age>18)limit(10)build()Queryready, valid objectnew Query(a, b, c, … 12 args)which argument is which?instead ofa readable chain replaces a monstrous constructor
Una cadena de pasos → build() → un objeto terminado. En lugar de un constructor donde no se sabe cuál argumento es cuál.
PatternBuilder· builder, constructor
Problema
Un constructor de doce argumentos, la mitad opcionales.
Idea
Fijá las partes una a una y después build().
Ejemplo

QueryBuilder().select("name").where("age > 18").limit(10).build().

Coste
Una clase más al lado de la real.
Cuándo usarlo
El objeto tiene muchas partes opcionales.
Relaciones

Factory decide qué construir; Builder decide cómo ensamblar algo complejo.

Singleton — exactamente uno, compartido por todos

Un país tiene un presidente. Todos los que dicen «el presidente» se refieren a la misma persona — no hay dos.

Un Singleton garantiza una única instancia con un solo punto de acceso global. Pero ojo: un singleton es estado global con abrigo bonito, y el estado global complica las pruebas y el razonamiento.

BillingAuthReportsAPIgetInstance()Configthe one instanceeveryone reaches the same global — handy, but hard to test
Todos los módulos llegan a la misma instancia — cómodo, pero es estado global.
PatternSingleton· singleton, único
Problema
Necesitás exactamente una instancia compartida.
Idea
La propia clase garantiza una instancia y un punto de acceso.
Ejemplo
Un objeto de configuración o un logger del que todos leen.
Coste
Estado global: probar y razonar se vuelve más difícil.
Cuándo usarlo

Rara vez. Una única instancia que pasás explícitamente suele ganarle a una a la que se llega por un global.

Relaciones
De creación como Factory, pero sobre «cuántos», no «cuál».

Prototype — copiá algo ya armado en lugar de construir de cero

Fotocopiar un formulario ya completado es más rápido que llenar uno en blanco desde cero.

Cuando hacer un objeto desde cero es caro o engorroso, un Prototype te deja clonar uno existente y ajustarlo. Útil cuando los objetos son costosos de construir y casi todos se parecen.

Enemyconfigured: hp, skin, AIclone() + tweakcopy #1tweak: colourcopy #2tweak: speedcopy #3as ischeaper thanbuilding from zerocopy a filled-in object instead of rebuilding its setup
Un objeto configurado se clona y se retoca un poco — en lugar de construirse otra vez.
PatternPrototype· prototype, prototipo
Problema
Construir el objeto desde cero es lento y engorroso.
Idea
Tomá un objeto listo, copialo, ajustá las diferencias.
Ejemplo

Duplicar un enemigo de juego ya configurado, o un nodo de documento con estilo.

Coste
Copiar exige cuidado: qué se copia y qué queda compartido.
Cuándo usarlo

Los objetos son costosos de construir y en su mayoría parecidos.

Relaciones
Una alternativa a Factory: no «construir», sino «copiar».

Escondé el new. Cuantos menos lugares sepan cómo se construye un objeto, más libre sos de cambiarlo.

§ 03

Cómo se componen los objetos en estructuras más grandes — encajando partes incompatibles y agregando capacidad sin reescribir.

Adapter — un convertidor de enchufe entre dos interfaces

El cargador de tu laptop en el extranjero — el aparato está bien, el enchufe está bien; solo hace falta el convertidor entre ambos.

Un Adapter envuelve una interfaz para que parezca otra, y deja que dos cosas que no fueron diseñadas para cooperar trabajen juntas. Es cómo evitás que la API de otro se filtre por todo tu código.

Your codeexpects your interfacepay()Adaptertranslates callscharge()Vendor SDKits own shapeyour code never sees the vendor's shape
Tu código llama a pay(); el adaptador lo traduce al charge() del proveedor.
PatternAdapter· adaptador, wrapper
Problema

La interfaz de otro no encaja con la tuya y se esparce por tu código.

Idea
Un envoltorio que traduce las llamadas de una interfaz a otra.
Ejemplo

Un SDK de pagos de terceros envuelto para que cumpla tu propio PaymentProvider.

Coste
Una capa más que actualizar cuando cambia la API del proveedor.
Cuándo usarlo
Al conectar código de terceros o heredado.
Relaciones

Envuelve un objeto como Decorator y Proxy, pero cambia la interfaz.

Decorator — agregá ingredientes sin cambiar la pizza

Una pizza simple, luego queso, luego champiñones — cada capa envuelve la anterior y agrega algo, y sigue siendo una pizza.

Un Decorator envuelve un objeto para agregar comportamiento sin modificar el original ni heredar de él. La interfaz sigue igual, así que las capas se apilan. Te deja sumar funciones en combinaciones que nadie tuvo que prever.

Encrypt decoratorCompress decoratorFileStreamthe originalwrite()each layer wraps the last, adds one thing, keeps the same interface
Un flujo envuelto en compresión, y eso envuelto en cifrado. Desde afuera sigue siendo un flujo.
PatternDecorator· decorador, wrapper
Problema

Necesitás extras en cualquier combinación; una subclase para cada uno no escala.

Idea
Envolvé el objeto, agregá un comportamiento, mantené la interfaz.
Ejemplo

Un flujo de datos → compresión → cifrado; cada capa se puede apilar o quitar.

Coste

Muchos envoltorios pequeños; una pila de capas es más difícil de depurar.

Cuándo usarlo
Las capacidades deben combinarse en tiempo de ejecución.
Relaciones

La misma forma que Proxy, pero el objetivo es agregar, no controlar. El caso de manual de composición sobre herencia.

Facade — una recepción simple frente a una oficina trasera desordenada

El conserje de un hotel — decís «necesito un taxi y una reserva para cenar», y él se ocupa del enredo de llamadas detrás del mostrador.

Una Facade da una entrada única y simple a un subsistema complicado, escondiendo sus piezas móviles. Reduce una superficie enorme a la única puerta que la mayoría de quienes llaman necesita.

ClientVideoConverterconvert(file, mp4)one doorfor most callerssubsystemCodecsBuffersAudio streams
Una sola llamada convert() — con códecs, búferes y flujos de audio detrás.
PatternFacade· fachada
Problema
Hacer algo simple exige conocer una docena de clases del subsistema.
Idea
Una puerta simple que orquesta el subsistema.
Ejemplo

VideoConverter.convert(file, "mp4") orquesta en silencio códecs, búferes y flujos de audio.

Coste

La complejidad no desaparece — queda oculta. El control fino sigue yendo por fuera de la fachada.

Cuándo usarlo

La mayoría de quienes llaman necesita uno o dos escenarios simples.

Relaciones

Adapter cambia la interfaz de una cosa; Facade simplifica todo un subsistema.

Proxy — un sustituto que controla el acceso

El asistente de una celebridad — no llegás a la estrella directamente; el asistente filtra, agenda y a veces responde por ella.

Un Proxy se para delante de un objeto para controlar el acceso — para carga perezosa (lazy loading), permisos, caché o para hablar con algo remoto. La misma interfaz, una puerta extra al frente.

ClientProxysame interfaceonly if neededRealImageheavy, loaded latelazy load · access checkcache · remote call
El cliente habla con el proxy como si fuera el objeto real; el proxy decide cuándo — y si — pasar la llamada.
PatternProxy· sustituto, stand-in
Problema

El objeto es caro de cargar, necesita permisos o vive en otra máquina.

Idea
Un sustituto con la misma interfaz se pone delante del objeto real.
Ejemplo

Un proxy de imagen que no carga el archivo real hasta que se muestra; un proxy de acceso que comprueba permisos antes de reenviar la llamada.

Coste
Un salto extra en cada llamada; latencia oculta para quien llama.
Cuándo usarlo
Carga perezosa, permisos, caché, objetos remotos.
Relaciones

La misma forma que Decorator, otro objetivo — control de acceso.

Composite — tratá igual a un árbol y a una hoja

Una carpeta contiene archivos y otras carpetas. «Calcular el tamaño» funciona igual si se lo pedís a un archivo o a todo el árbol.

Un Composite te deja tratar de forma uniforme a un objeto individual (una hoja) y a un grupo de objetos (un compuesto) — comparten una sola interfaz. Convierte las estructuras recursivas en algo que manejás sin casos especiales en cada nivel.

Folderfile.txtFolderphoto.jpga.mdb.mdgetSize() and render() work the same on one leaf and on a whole tree
Una carpeta y un archivo responden a las mismas llamadas — el árbol se recorre sin casos especiales.
PatternComposite· compuesto, árbol
Problema
Trabajar con un árbol exige un caso especial en cada nivel.
Idea
Hoja y rama comparten una interfaz; una rama solo llama a sus hijos.
Ejemplo

Una UI donde un botón y un panel lleno de botones responden ambos a render() y getSize().

Coste

La interfaz común puede ser demasiado general: no toda operación tiene sentido en una hoja.

Cuándo usarlo
Los datos son naturalmente un árbol: carpetas, UI, documentos.
Relaciones

Se recorre con Iterator; las operaciones nuevas se agregan con Visitor.

Composición sobre herencia: unir comportamiento en tiempo de ejecución en lugar de congelarlo en un árbol de clases.

§ 04

La primera mitad de los patrones de comportamiento: cómo los objetos reparten el trabajo y se hablan — para que la responsabilidad quede bien dividida y el código correcto corra en el momento correcto.

Strategy — cambiá el algoritmo, mantené al que llama

Una app de mapas: el mismo viaje, pero elegís «más rápido», «más corto» o «evitar peajes», y traza otra ruta. Vos elegís la estrategia; la app solo la sigue.

Una Strategy vuelve intercambiable un algoritmo en tiempo de ejecución, así que quien llama sigue igual mientras el método varía. En los lenguajes modernos suele ser simplemente pasar una función en vez de toda una clase — y ese es el punto: el patrón es la idea, no la ceremonia.

Checkoutuses a strategyPricingStrategyinterface / functionRegularMemberHolidaySaleswap the algorithm at runtime; the caller never changes
El checkout llama a una PricingStrategy; qué precio aplica se decide en tiempo de ejecución.
PatternStrategy· estrategia
Problema

Una escalera de if que crece sobre variantes de un mismo algoritmo.

Idea

El algoritmo es un objeto (o función) intercambiable detrás de una interfaz.

Ejemplo

Un checkout que recibe una PricingStrategy: normal, de socio o de rebajas de temporada.

Coste
Una Strategy para un algoritmo que nunca varía es peso muerto.
Cuándo usarlo
Dos o más variantes, elegidas en tiempo de ejecución.
Relaciones

La misma forma que State. En el código moderno, a menudo solo una función.

Observer — suscribite y te avisan cuando cambia

Un boletín — te suscribís una vez, y cada número nuevo te llega. El editor no llama a cada lector; solo envía a la lista.

Con un Observer, los suscriptores se registran en un sujeto y reciben aviso cuando cambia — sin que el sujeto sepa quiénes son. Es la columna vertebral del código orientado a eventos y reactivo.

notify()Subjectspreadsheet cellChartPivot tableSummarythe subject keeps a list of subscribers — it doesn't know who they are
La celda cambia → notify() → cada gráfico y tabla que depende de ella se actualiza solo.
PatternObserver· observador, pub/sub
Problema

Un objeto debe avisar a muchos otros de un cambio sin conocerlos por nombre.

Idea
Una lista de suscriptores + notify() en cada cambio.
Ejemplo

Una celda de hoja de cálculo que refresca cada gráfico que depende de ella; los frameworks de UI reaccionando al estado; pub/sub por todas partes.

Coste

Las cadenas de avisos son difíciles de seguir; una suscripción olvidada vive para siempre.

Cuándo usarlo
Varias partes independientes reaccionan a un mismo cambio.
Relaciones

La base del código orientado a eventos — lo mismo que la arquitectura Event-driven, dentro de un solo programa.

Command — envolvé una petición como un objeto

Una comanda de restaurante — la petición «mesa 5, dos cafés» se vuelve un papelito que podés encolar, reordenar, registrar e incluso romper.

Un Command convierte una acción en un objeto independiente, para que puedas encolarla, registrarla, programarla o deshacerla. Es cómo una acción se vuelve algo que podés guardar y reproducir.

Editoruser actioncommand historyTypeTextdo() · undo()Bolddo() · undo()Deletedo() · undo()executeDocumentreceiveran action becomes an object: queue it, log it, undo it, replay it
Cada edición es un objeto con do() y undo(); el historial de comandos da deshacer/rehacer y macros.
PatternCommand· comando
Problema
Una acción debe posponerse, repetirse, registrarse o deshacerse.
Idea
Empaquetá la acción en un objeto con todo lo necesario para ejecutarla.
Ejemplo

Cada edición en un editor es un comando — de ahí deshacer/rehacer y las macros. Una cola de trabajos son comandos esperando su turno.

Coste
Un objeto por acción; hay que pensar el deshacer para cada comando.
Cuándo usarlo
Deshacer/rehacer, colas, macros, un registro de acciones.
Relaciones
A menudo va junto con Memento para deshacer.

Chain of Responsibility — pasalo hasta que alguien lo atienda

Los niveles de soporte al cliente — la recepción lo intenta, escala a un especialista, luego a un gerente, hasta que alguien puede resolverlo de verdad.

Con una Chain of Responsibility, una petición viaja por una cadena de manejadores; cada uno o la atiende o la pasa. Desacopla al que envía de quien termina haciendo el trabajo.

middleware chainRequestAuthLoggingRate limitRoutehandles it401, stopeach link handles its part — or passes the request on
Middleware web: autenticación → registro → límite de tasa → ruta. Cualquier eslabón puede detener la petición.
PatternChain of Responsibility· cadena de responsabilidad, middleware
Problema

El que envía no debería saber quién exactamente atenderá la petición.

Idea
Una cadena de manejadores: cada uno hace su parte o la pasa.
Ejemplo

Middleware web: autenticación, luego registro, luego límite de tasa, luego la ruta misma.

Coste

El orden de los eslabones importa; una petición puede recorrer toda la cadena sin ser atendida.

Cuándo usarlo

Varias comprobaciones o pasos independientes antes del trabajo principal.

Relaciones
En la web casi siempre te lo encontrás como middleware.

Los buenos patrones de comportamiento dejan que dos piezas cooperen sin que ninguna deje a la otra cableada.

§ 05

La segunda mitad de los patrones de comportamiento: cómo cambia el comportamiento de un objeto con su estado, cómo recorrés colecciones y cómo fijás un esqueleto dejando un paso abierto.

State — comportamiento que cambia con el modo en que estás

Un semáforo — verde, amarillo, rojo — donde cada color decide qué pasa ahora y qué color viene después. El mismo semáforo, otro comportamiento según el estado.

El patrón State deja que un objeto cambie su comportamiento cuando cambia su estado interno. Un enredo de if y switch se vuelve estados y transiciones claros — una pequeña máquina de estados. Convierte un lío de banderas en una máquina ordenada.

pendingpaidshippedcancelledpay()ship()cancel()cancel()each state knows only its own rules and what it can become
Un pedido: pendiente → pagado → enviado; solo se puede cancelar desde pendiente o pagado.
PatternState· estado, state machine
Problema

El comportamiento depende de un modo, y el código se llena de banderas y switch.

Idea
Cada estado es su propio objeto con sus propias reglas y transiciones.
Ejemplo

Un pedido que se comporta distinto como pending, paid, shipped o cancelled; cada estado conoce solo sus reglas y en qué puede convertirse.

Coste
Muchas clases pequeñas; para dos estados basta un if simple.
Cuándo usarlo
Muchos estados, y las transiciones entre ellos importan.
Relaciones

La misma forma que Strategy, pero el objeto cambia de estado por sí mismo mientras vive.

Iterator — recorré una colección sin ver sus entrañas

Los botones siguiente y anterior de un control remoto — pasás por los canales sin saber cómo están guardados.

Un Iterator da una forma uniforme de recorrer una colección sin exponer cómo está hecha — arreglo, árbol o lista enlazada. Este es tan útil que el lenguaje suele traerlo incorporado — for..of, generadores, __iter__. Es la señal más clara de que un patrón puede graduarse a una característica del lenguaje.

ArrayTreeLinked listIteratornext() · hasNext()for..of loopsame code for allwalk any collection without seeing how it is stored
Arreglo, árbol y lista entregan el mismo next() — el bucle no sabe qué hay dentro.
PatternIterator· iterador
Problema
El código de recorrido depende de cómo está construida la colección.
Idea

Una sola forma de obtener «el siguiente elemento», sea lo que sea que haya dentro.

Ejemplo

for (item of collection) funciona igual sobre una lista o una estructura propia.

Coste
Casi cero — normalmente ya viene incorporado en el lenguaje.
Cuándo usarlo
Siempre — pero con las herramientas incorporadas, no a mano.
Relaciones
Recorre los árboles construidos con Composite.

Template Method — una receta fija con un hueco para llenar

Una receta idéntica siempre — salvo «agregá la especia que prefieras» en el paso cuatro. El esqueleto es fijo; un paso es tuyo.

Un Template Method define el esqueleto de una operación en una clase base y deja que pasos específicos se sobrescriban sin cambiar la forma general. Útil cuando muchos flujos comparten forma pero difieren en un punto o dos.

fixed skeleton in the base classopen()read()parse()you fill this insave()CSV parseJSON parsesubclasses supplyonly this one step
Un importador base abre, lee, parsea y guarda; las subclases aportan solo el paso de parseo.
PatternTemplate Method· método plantilla
Problema
Varios flujos de la misma forma se copian casi por completo.
Idea

El esqueleto vive en una clase base; los pasos que varían viven en las subclases.

Ejemplo

Un importador que abre, lee, parsea (esto lo llenás vos) y guarda; los importadores de CSV y JSON aportan solo el paso de parseo.

Coste
Depende de la herencia; el esqueleto es difícil de cambiar después.
Cuándo usarlo

La forma es compartida, las diferencias están en uno o dos puntos.

Relaciones

Strategy resuelve un problema parecido con composición en lugar de herencia.

Mediator, Visitor, Memento — el resto, en un suspiro

Una caja de herramientas tiene instrumentos que usás una vez al mes, no a diario — pero igual conviene saber que existen.

Unos pocos más se ganan su lugar de vez en cuando. Mediator — una torre de control para que los objetos hablen por un solo centro en vez de un enredo de enlaces directos. Visitor — agregar operaciones nuevas a una estructura sin editar sus clases. Memento — capturar el estado de un objeto para restaurarlo después. Conocé los nombres; echá mano de ellos solo cuando aparezca el problema exacto.

MediatorVisitorMementoABCDHubone hub, not a tangleCircleSquareTextExportVisitornew operationclasses stay untouchedEditorSnapshotsaved statesaverestoreundo · save points
Mediator: todo a través de un centro. Visitor: una operación nueva recorre las clases desde afuera. Memento: instantánea y restauración.
PatternMediator· mediador
Qué es

Un centro por el que hablan los objetos en lugar de enlazarse directamente entre sí.

Imagen
Una torre de control: los aviones hablan con ella, no entre sí.
Cuándo usarlo
Los enlaces directos entre objetos se han vuelto demasiados.
PatternVisitor· visitante
Qué es
Una operación nueva sobre una estructura, movida a su propio objeto.
Ejemplo

Exportar cada figura de un documento — sin editar las clases de las figuras.

Cuándo usarlo

La estructura es estable, pero las operaciones sobre ella no paran de multiplicarse.

PatternMemento· instantánea, snapshot
Qué es
Un estado guardado de un objeto al que se puede volver.
Ejemplo

Puntos de guardado en un juego, instantáneas de deshacer en un editor.

Relaciones
Junto con Command te da el deshacer.

Cuando un patrón se vuelve palabra clave del lenguaje, dejá de escribir el patrón y usá la palabra clave.

§ 06

El catálogo es décadas de sabiduría ganada a pulso — y también un producto de su época. Usalo como un ingeniero sénior, no como una lista de verificación.

Language features — muchos patrones ya vienen incorporados

Antes dábamos indicaciones por puntos de referencia; ahora el teléfono navega. La habilidad no desapareció — fue absorbida por la herramienta.

Iterator es for..of. Strategy suele ser una función que se pasa. Decorator y Observer son ciudadanos de primera en los frameworks modernos. Cuando el lenguaje te da la forma gratis, escribir el patrón completo a mano es solo ceremonia (código repetitivo, boilerplate). La idea sigue importando; el boilerplate casi nunca.

the patternwhat the language gives you nowIteratorfor..of · generators · __iter__Strategya function passed inDecoratorbuilt into frameworksObserverreactive state in UI frameworks
A la izquierda, el patrón del catálogo; a la derecha, lo que el lenguaje o el framework ya te da en su lugar.

Pattern-itis — una enfermedad real

Un cocinero que vacía todo el estante de especias en un plato no obtiene una comida más rica — obtiene una incomible.

La Pattern-itis es el clásico olor a sobreingeniería (over-engineering): echar mano de patrones para parecer sofisticado. Y ahora es peor — un asistente de IA generará con gusto una «Abstract Factory multinivel» para lo que deberían ser tres líneas. El código más simple casi siempre es la elección más sénior.

Anti-patternPattern-itis· pattern-itis, sobreingeniería, over-engineering
Qué es
Patrones por sí mismos, no para aliviar un dolor.
Síntomas

Una fábrica abstracta para un solo producto, una Strategy para un algoritmo que nunca varía, cinco capas de indirección alrededor de un if.

Por qué ahora es peor

Los asistentes de IA generan estas estructuras con ganas y rápido.

Remedio

Primero el código más simple; un patrón solo cuando aparezca el dolor.

Los patrones son un vocabulario, no una ley

Conocer muchas palabras no hace a un buen escritor. Saber cuál palabra — y cuándo callar — sí.

El valor real del catálogo es el lenguaje compartido: «pongamos una Facade acá» le llega al instante a cualquiera que conozca el término, y eso vale mucho en un equipo. Pero la meta es siempre el código más simple que resuelva el problema. El patrón es un medio; nombrar uno nunca es el logro.

Aprendé todos los patrones para poder reconocerlos. Usá los menos que puedas.

§ 07

Los patrones son respuestas. La habilidad es hacerlos corresponder con una pregunta real — y saber cuándo ningún patrón es la respuesta correcta.

Dejá que el patrón surja del dolor

No elegís una llave antes de encontrar el tornillo. Ves el problema, y después echás mano de la herramienta que le calza.

El buen uso de patrones suele ser un refactor, no un plano de partida: escribís lo simple, sentís un dolor concreto — esta escalera de if no deja de crecer, esta clase sabe demasiado de cómo se construye — y entonces el patrón que lo alivia resulta obvio. Forzar patrones de entrada es como se construyen catedrales que nadie pidió.

Nombralo solo cuando el nombre ayude

No decís «ejecuté una pared» en una charla casual. Pero en la cancha, con tus compañeros, la palabra ahorra una oración entera.

La ganancia de un patrón es comunicación y flexibilidad. Si nombrarlo vuelve el código más claro para la próxima persona, usá el nombre en voz alta — en el nombre de una clase, un comentario, una charla de diseño. Si la indirección no compra nada, gana el código más llano, sea o no un patrón.

Los patrones están conectados

Las palabras de un idioma no viven solas: tienen sinónimos, pares y parientes.

Adapter, Decorator y Proxy son una misma forma: un envoltorio alrededor de un objeto, con objetivos distintos. Strategy y State se parecen en la forma. Command y Memento juntos dan el deshacer. Abstract Factory está construida a partir de Factory. Composite se recorre con Iterator. Observer es la columna vertebral del código orientado a eventos.

all wrap one objectAdapterchanges the interfaceDecoratoradds behaviourProxycontrols accessStrategyStatesame shapeCommandMementoundoAbstract FactoryFactoryusesCompositeIteratorwalk the treeObserverEvent-driven codebackbone ofChain of Responsibility= web middleware
Los vínculos principales entre los patrones del curso.
Antes de echar mano de un patrón
  • ¿Qué problema recurrente resuelve? Decilo en una oración.
  • ¿Tengo ese problema ahora, o estoy adivinando el futuro?
  • ¿Bastaría una función u objeto simple? Probá eso primero.
  • ¿Mi lenguaje ya me da esto gratis?
  • ¿Nombrarlo volverá el código más claro para la próxima persona — o solo más elegante?
  • ¿Estoy refactorizando hacia él, o lo estoy forzando de entrada?
Pruebas de olor de que sobreingenierizaste
  • Tenés una fábrica que construye exactamente una cosa.
  • Una Strategy con una sola estrategia que nunca cambia.
  • Más interfaces e indirección que comportamiento real.
  • Agregaste el patrón para parecer sénior, no para resolver un dolor.
  • Un lector nuevo necesita un diagrama UML para seguir tres líneas de lógica.
Señales de que elegiste bien
  • El patrón eliminó una escalera de if/switch que no dejaba de crecer.
  • Podés cambiar una implementación sin tocar a quienes llaman.
  • Un compañero reconoció la forma al instante por su nombre.
  • La indirección se gana su lugar — de verdad usás la flexibilidad.
  • El código es más simple con el patrón que sin él, no solo más ingenioso.

Hoja de referencia: los 20 patrones y las ideas clave

Fundamentos

Design Patternpatrón de diseño

Una solución con nombre a un problema recurrente en el código. Vocabulario, no una librería.

Gang of FourGoF

Los autores de Design Patterns, que catalogaron 23 patrones.

Indirectionindirección

Una capa entre vos y la cosa. El coste de todo patrón.

Pattern-itissobreingeniería, over-engineering

Patrones de vitrina, no de dolor. El código simple casi siempre gana.

De creación

FactoryFactory Method, fábrica

Pedí un objeto por su nombre; la fábrica elige la clase.

Abstract Factoryfábrica abstracta

Una fábrica para toda una familia de objetos que combinan.

Builderconstructor

Un objeto complejo paso a paso, y después build().

Singletonúnico

Exactamente una instancia para todos. Ojo: estado global.

Prototypeprototipo

Cloná un objeto listo y retocalo.

Estructurales

Adapteradaptador

Un convertidor: una interfaz parece otra.

Decoratordecorador

Un envoltorio agrega comportamiento; la interfaz sigue igual.

Facadefachada

Una puerta simple a un subsistema complejo.

Proxysustituto

Se para delante de un objeto y controla el acceso.

Compositecompuesto

Una hoja y un árbol comparten una interfaz.

De comportamiento: hablar

Strategyestrategia

Un algoritmo intercambiable; a menudo solo una función.

Observerobservador

Los suscriptores reciben aviso de los cambios.

Commandcomando

Una acción como objeto: encolar, registrar, deshacer.

Chain of Responsibilitycadena de responsabilidad, middleware

Manejadores en cadena; en la web, middleware.

De comportamiento: estado y pasos

Stateestado

Cada estado tiene sus propias reglas y transiciones.

Iteratoriterador

Recorrer una colección sin mirar adentro. Normalmente for..of.

Template Methodmétodo plantilla

El esqueleto es fijo; un paso es tuyo.

Mediatormediador

Todos hablan por un solo centro.

Visitorvisitante

Una operación nueva sin editar las clases.

Mementoinstantánea

Guardar un estado y volver a él.

El mejor uso de un patrón de diseño es el que un lector nunca nota — porque hizo que el código pareciera obvio.

Fin del curso exprés · 7 capítulos · 20 patrones

Lo que sigue es la fuente: Design Patterns de la Banda de los Cuatro, y sus compañeros modernos más amables — Head First Design Patterns, refactoring.guru, Refactoring de Martin Fowler. Pero leelos como aprenderías aperturas de ajedrez: no para memorizar jugadas, sino para reconocer la posición cuando aparezca en tu propio tablero.