Patrones de Diseño Software de Creación

Introducción

Los patrones de diseño software de creación proporcionan ayuda a la hora de crear objetos desde el punto de vista de proporcionar un apopyo en la toma de decisiones, incluso cuando esta toma de decisiones sea de forma dinámica.
Gracias a ello, ayudan a estructurar y encapsular estas decisiones. Hay ocasiones en la que nos encontraremos con que sólo existe un patrón adecuado; otras en las que varios podrán ayudarnos; y otras en que se pueden combinar múltiples patrones convenientemente.
Un patrón de creación asociado a clases usa la herencia para variar la clase que se instancia, mientras que un patrón de diseño software de creación asociado a objetos delegará la instanciación a otro objeto.

Hay dos formas de clasificar los patrones de diseño software de creación basándose en las clases de objetos que se crean. Una es clasificar las clases que crean los objetos (Factory Method), y la otra forma está relacionada con la composición de objetos (definir un objeto que es responsable de conocer las clases de los objetos producto). En esta característica se apoyan los patrones Abstract Factory, Builder o Prototype.
En muchas ocasiones los patrones de creación compiten en su función. Por ejemplo, hay casos donde los patrones de creación Protoype y Abstract Factory puede utilizarse indistintamente. En otras ocasiones Builder puede usar a los otros patrones para implementar los componentes que construye.

A continuación, definiremos algunos de los patrones de diseño software de creación más habituales.


Abstract Factory

Nos encontramos frente a un problema en el que debemos crear diferentes objetos, todos pertenecientes a la misma familia, como puede ser el sistema de librerías necesarias para crear interfaces gráficas. Visto esto podríamos decir que lo que intenta solucionar el patrón de diseño software de creación Abstract Factory es crear diferentes familias de objetos. El patrón Abstract Factory, por tanto, se recomienda cuando se atisba la inclusión de nuevas familias de productos en un futuro, pero resultaría contraproducente si que necesita añadir nuevos productos o modificar los existentes, ya que tendría repercusión en todas las familias creadas.

Según esto, podemos decir que los componentes típicos del patrón Abstract Factory es la siguiente:

  • Cliente: Entidad que llamará a la fábrica adecuada que necesite para crear uno de los objetos que provee dicha factoría, es decir, intentará obtener una instancia de alguno de los productos que entren en juego (ProductoA, ProductoB).
  • AbstractFactory: Definición de la interfaz que usarán las diferentes factorías. Como mínimo, debe ofrecer un método para la obtención de cada objeto que se pueda crear. ("crearProductoA()" y "crearProductoB()")
  • Concrete Factories: Aquí se representarán las diferentes familias de productos. Provee la instancia concreta del objeto que se encarga de crear.
  • Abstract Product: Definirá las interfaces para la familia de productos genéricos. En el diagrama son "ProductoA" y "ProductoB". El cliente trabajará directamente sobre esta interfaz, que será implementada por los diferentes productos concretos.
  • Concrete Product: Se encargará de la implementación específica de los diferentes productos.

Este sería el diagrama de clases general del patrón de creación Abstract Factory:

Esquema Abstract Factory
Esquema del patrón Abstract Factory

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación Abstract Factory.



Factory Method

Este patrón de diseño software de creación consiste en utilizar una clase constructora abstracta (similar al concepto del patrón Abstract Factory) con unos métodos definidos y otro(s) abstracto(s): el(los) dedicado(s) a la construcción de objetos de un subtipo determinado.
Como vemos, es una simplificación del Abstract Factory, en la que la clase abstracta tiene métodos concretos que se relacionan con los abstractos, de modo que según usemos una u otra "hija" de esta clase abstracta, tendremos uno u otro comportamiento.

El patrón de diseño software de creación Factory Method puede ser usado cuando:

  • La creación de un objeto impide su reutilización sin una importante duplicación de código.
  • La creación de un objeto requiere acceso a la información o recursos que no deberían estar contenidos en la clase de composición.
  • La administración de la duración de los objetos generados debe ser centralizada para garantizar un comportamiento coherente en la aplicación.

Por tanto, los componentes del patrón de creación Factory Method sería:

  • Product: define una interfaz de un objeto que metodo Factory creara.
  • ConcreteProduct: implementa la interfaz Product para crear un producto en concreto.
  • Creator: declara el metodo factory que devolvera un objeto del tipo product.
  • ConcreteCreator: sobre escribe e metodo factory del creator devoler una intancia de un producto en concreto (ConcreteProduct).

Este sería el diagrama de clases general de este patrón de creación:

Esquema Factory Method
Esquema del patrón Factory Method

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación Factory Method.



Prototype

El patrón de diseño de software de creación Prototype, sirve para crear un duplicado de un objeto, clonando, para ello, una instancia de ese objeto que ya haya sido creada. Para ello, el patrón tiene que especificar el tipo de objeto que quiere clonar, creando así un 'prototipo' de esa instancia. Este tipo o clase de objetos deberá contener en su interfaz el procedimiento que permita solicitar esa copia, siendo desarrollado luego por las clases concretas del patrón que deseen crear ese clon.

Como podemos ver, la principal razón de uso de este patrón de diseño software de creación es crear las distintas clases de objetos que necesite el sistema, y hacerlo en el momento y entorno adecuados. Eso sí, la lógica y diseño que necesite el sistema para la ejecución y decisión de la creación de estos objetos copia, se hace de forma independiente al patrón, siendo éste referido cuando el fragmento de código pertinente solicite una copia del objeto que necesite. Cabe destacar que hacer una 'copia' significa crear otra instancia del objeto (siempre que este tenga la funcionalidad de clonarse) con las particularidades necesarias en ese instante.

Desacar también, que el API de Java dispone de interfaz Cloneable que facilita la implementación de este patrón, haciéndola compatible con otros prototipos que se encuentran en las diferentes librerías de Java.

Este sería el diagrama de clases general del patrón:

Esquema Singleton
Esquema del patrón Prototype

Visto esto, los actores que intervienen en el patrón de creación Prototype, son:

  • Cliente: actor solicitante de la creación (clonación) de los nuevos objetos a partir de los prototipos.
  • Prototipo Concreto: actor (clase) que presenta unas características concretas que serán reproducidas en los nuevos objetos y que presenta la implementación necesaria para clonarse.
  • Prototipo: declara una interfaz, al a que accede el cliente, que sirve para la clonación de objetos.

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación Prototype.



Singleton

El patrón de diseño de software de creación Singleton (haciendo referencia a una instancia única) busca restringir la creación de objetos pertenecientes a una clase o el valor de un tipo a un único objeto. Su intención es garantizar que una clase sólo sea instanciada una vez y, además, proporcionar un único punto de acceso global a la misma. Esto lo consigue gracias a que es la propia clase la responsable de crear esa única instancia, (declarando el constructor de la clase como privado) y a que se permite el acceso global a dicha instancia mediante un método de clase.

Para implementar el patrón singleton hay que crear un método que instancie al objeto sólo si todavía no existe ninguna otra instancia. Para asegurar que no vuelva a ser instanciado, se limita al constructor con atributos protegidos o privados. Por esto, la implementación del patrón puede ser complicada en programas multihilo, ya que si dos o más hilos de ejecución instanciaran la clase al mismo tiempo sólo uno de ellos debería lograr crear el objeto. La solución clásica para este problema es utilizar exclusión mutua en el método de creación de la clase que implementa el patrón. Ejemplos de situaciones habituales en las que convendría aplicar este ejemplo de patrón de diseño son aquellas en las que la clase principal busca controlar el acceso a un recurso único (como puede ser el ratón o un archivo abierto en modo exclusivo) o cuando cierto tipo de datos debe estar disponible para todos los demás objetos.

Este sería el diagrama de clases general del patrón de creación Singleton:

Esquema Singleton
Esquema del patrón Singleton

En este enlace podrá consultar un código de ejemplo en Java del patrón de creación Singleton.