Los Patrones de Diseño Hoy: Patrones Creacionales

Todo desarrollador que se precie debería conocer los patrones de diseño, y especialmente los clásicos de la GoF. Aunque vivieron su momento de hype, siguen siendo útiles a la hora de desarrollar, sobre todo porque facilitan mucho la comunicación entre desarrolladores al poder estandarizar el nombre las cosas.

Teniendo en cuenta que el libro que originó todo esto es de 1994 y que en estos últimos 22 años los lenguajes y estilos de programación han tenido su evolución, he pensado que podría ser entrenido ver qué tal ha aguantado el paso del tiempo cada patrón de los 23 que aparecían en el catálogo original. Como son unos cuantos, voy a dividirlo en 3 posts, siguiendo las categorías que aparecen en el propio libro: patrones creacionales, patrones estructurales y patrones de comportamiento.

Todo esto es bastante personal y depende mucho del estilo de programación de cada uno y de los lenguajes que utilice, así que no te lo tomes como algo excesivamente serio. De hecho, en este post hay un claro sesgo hacia lenguajes orientados a objetos porque, como todos sabéis, en programación funcional todos los problemas de diseño se solucionan con funciones ;-)

No voy a entrar en detalle a describir cada patrón porque para eso ya hay miles de páginas en internet. Si no los conoces, te recomiendo que hagas una búsqueda rápida porque merece la pena que, por lo menos, te suenen.

Empezamos con los patrones creacionales.

Abstract Factory

Si necesitas tener distintas implementaciones de una factoría para generar distintas familias de clases, probablemente tu arquitectura sea demasiado complicada. En serio, tener un AbstractMembershipProviderFactory que sirve para abstraer las distintas implementaciones de factorías capaces de crear distintas implementaciones de MembershipProvider es como para detenerse a pensar si realmente te hacen falta tantos grados de indirección.

Ojo, no hay que confundir este patrón con el patrón factory (sin el abstract), donde tenemos un objeto (la factoría) que es capaz de crear distintos de objetos o incluso distintas configuraciones de un mismo objeto. Este patrón tiene muchos más usos y es rara la aplicación medianamente compleja en la que no aparece varias veces.

Aplicando el patrón factory (sin el abstract) en un par de puntos concretos de la aplicación, muchas veces te puedes ahorrar montar todo el sistema completo de inyección de dependencias con un contenedor y conseguir resultados similares con un código mucho más sencillo de seguir.

Utilidad hoy en día: 2 con abstract, 5 sin abstract.

Builder

Un patrón al que me costó mucho tiempo verle la utilidad real, pero que ha encontrado un hueco muy importante en mi estilo de programación a la hora de escribir tests.

Otro escenario en el que se utiliza bastante es al diseñar interfaces fluidos de esos que estaban tan de moda hace 8 años. Me gusta especialmente cuando se usa para preparar la construcción de la configuración que se usará luego en tiempo de ejecución, al estilo de lo que se hace con Fluent NHibernate o con el IAppBuilder de OWIN.

Saliendo de esos dos escenarios, tests e interfaces fluidos, la verdad es que no lo uso demasiado. Es raro que construya tantas veces un mismo tipo de objeto y con tantas configuraciones diferentes como para que me compense montar un builder.

Utilidad hoy en día: 3.

Factory Method

La definición original de factory method nunca me ha acabado de convencer. De hecho, la diferencia con template method es realmente sútil (esto pasa con más patrones), ya que consiste en tener un método abstracto o virtual en una clase base para construir algo, y dejar que las clases derivadas decidan exactamente qué y como implementar.

Aunque eso tiene sus usos, hay otra forma de ver el factory method que sí utilizo más y me parece más práctica: tener un método estático que construye objetos. A diferencia de un factory, que es una clase entera dedicada a construir cosas, aquí tenemos uno o más método estáticos para construirlas, y estos métodos residen generalmente en la clase base de la jerarquía de clases que estamos construyendo. Un ejemplo es SymmetricAlgorithm.Create o WebRequest.Create.

Lo utilizo bastante para poder simular «constructores con nombre» y que quede más claro lo que estoy creado. Por ejemplo, Color.FromRGB y Color.FromHexString, o Result.Success(value) y Result.Error(exception).

Utilidad hoy en día: 2 (el factory/template method original), 4 (el factory method as named constructor).

Prototype

Si nos ceñimos únicamente a clonar objetos, que es lo que dice el patrón original, la cosa se queda un poco triste. Si ampliamos la idea a construir objetos a partir de otros con las modificaciones que queramos, se hace más interesante. Puede parecer que no se usa mucho, y tal vez en C# sea así, pero hay otros lenguajes en lo que resulta muy habitual.

En Javascript se utiliza continuamente, y no me refiero a la herencia prototípica que casi nadie aprovecha conscientemente, sino a esto:

var opts = Object.assign({}, defaultOpts, customOpts)

Clonando el objeto defaultOps y modificándolo con el contenido de customOpts creamos las opciones reales.

También es habitual verlo en lenguajes que favorecen el uso de estructuras de datos inmutables, donde partiendo de una estructura que sirve de base, se «clona» (en realidad se reutiliza, aprovechando su inmutabilidad) y sirve de base para crear la siguiente versión de la estructura.

Utilidad hoy en día: 3.

Singleton

El pobre singleton. Creo que fue el primer patrón de diseño que conocí y entendí (al igual que mucha gente). De ahí al abuso… bueno, ya sabemos todos como acabó el singleton.

Pese a su mala fama, sigue teniendo su uso y, al igual que ocurre con los métodos estáticos, se pueden salvar muchos de sus problemas. Aun así, su utilidad es limitada y suelo preferir separar la gestión del ciclo de vida de la clase de la propia clase, dejando que sea otro el que lo gestione.

En general, antes de utilizar un singleton prefiero utilizar una fachada estática. Pierdes la parte de la inicialización perezosa, pero te ahorras algo de código al no tener que andar poniendo el Instance o getInstance() por todas partes.

Utilidad hoy en día: 2.

Conclusión

En este post hemos repasado los 5 patrones creacionales clásicos y, en conjunto, podríamos decir que gozan de una salud bastante razonable, y más teniendo en cuenta que vienen de una época en la que no existía ni Java.

Algunos de ellos como AbstractFactory y Singleton han caído más en desuso, en parte por sus propios defectos (excesiva complejidad o excesivo acoplamiento), pero también porque cuando los contenedores de inversión de control se hicieron mainstream parte de las problemas que solucionaban estos patrones quedaban resueltos por el propio contenedor.

Las factorías (no abstract) y los factory methods (como constructores estáticos) son dos patrones que utilizo con mucha frecuencia y creo que aportan bastante en forma de abstracción y legibilidad al tratar con jerarquías de clases, o incluso con una única clase cuando queremos resaltar muy bien las características de la instancia que estamos construyendo.

Builder y Prototype son dos patrones de uso más limitado. Cuando son útiles, resultan muy útiles, pero lo cierto es que no los utilizo con tanta frecuencia.

Un comentario en “Los Patrones de Diseño Hoy: Patrones Creacionales

  1. Llevo 2 años leyendo este blog y acabo de descubrir con el link de las fachadas estáticas que ya había oro antes de mi descubrimiento… Tengo mucho que leer.

Comentarios cerrados.