Patrón de diseño Factory: las claves del patrón Factory Method

Desde que se publicara en 1994, se han vendido más de 500 000 copias de Patrones de diseño: elementos de software orientado a objetos reutilizables. Este libro para desarrolladores de software describe 23 patrones de diseño, también conocidos en círculos profesionales como los patrones de diseño de la Gang of Four, un término que se refiere a los cuatro autores del libro: Erich Gamma, John Vlissides, Ralph Johnson y Richard Helm.

Entre las diversas estrategias de diseño expuestas en esta publicación, se encuentra el factory method, que permite que una clase delegue en las subclases la creación de objetos. En concreto, es el patrón del factory method, que actualmente suele conocerse simplemente como Factory Pattern, el que se utiliza para explicar cómo se usa este práctico método.

¿Qué es el Factory Pattern?

El patrón Factory, o patrón de diseño Método Factoría, describe un enfoque de programación que sirve para crear objetos sin tener que especificar su clase exacta. Esto quiere decir que el objeto creado puede intercambiarse con flexibilidad y facilidad. Para implementar este método, los desarrolladores utilizan el Factory Method, que da nombre a este patrón. Su uso puede especificarse en una interfaz o implementarse mediante la clase hijo o la clase base y opcionalmente sobrescribirse (mediante clases derivadas). Al hacerlo, el patrón o método toma el lugar del constructor de clase normal para separar la creación de objetos de los propios objetos. Como resultado, es posible seguir los principios SOLID.

Nota

Los principios SOLID son un subgrupo de principios del diseño orientado a objetos que pretenden mejorar el proceso de desarrollo del software orientado a objetos. El acrónimo SOLID hace referencia a los cinco principios siguientes:

- Single responsibility principle o principio de responsabilidad única: cada clase debería tener solo una responsabilidad.

- Open/closed principle o principio de abierto/cerrado: las entidades de software deberían ser expandibles sin necesidad de cambiar su comportamiento.

- Liskov substitution principle o principio de sustitución de Liskov: siempre debería utilizarse la clase derivada en vez de la clase base.

- Interface segregation principle o principio de segregación de la interfaz: las interfaces deberían adaptarse perfectamente a los requisitos de los clientes que acceden.

- Dependency inversion principle o principio de la inversión de la dependencia: las clases que tienen un mayor nivel de abstracción nunca deberían depender de las clases con un nivel de abstracción menor.

En muchos casos, se usa el término abreviado Factory Pattern (patrón Factory) o Factory Design Pattern (patrón de diseño Factoría) a pesar de que la Gang of Four no lo define así en el libro. De hecho, si examinamos en profundidad el libro, veremos que además del Factory Method que comentamos en este artículo, solo existe el similar patrón Factory abstracto, que define a una interfaz para la creación de una familia de objetos, cuyas clases concretas solo se definen durante el tiempo de ejecución.

¿Cuál es la finalidad del patrón Factory?

El Factory Pattern se propone resolver un problema fundamental de la instanciación (la creación de un objeto concreto de una clase) en la programación orientada a objetos. En principio, es posible crear un objeto directamente en la clase que requiere o en la que debería estar, pero también es muy inflexible. Hacer esto vincula la clase al objeto en cuestión y es imposible cambiar la instanciación al margen de la clase. Este tipo de código se evita en el patrón Factory definiendo una operación aparte para crear el objeto: el Método Factoría. En cuanto se llama, este método genera el objeto en vez del constructor de clase que ya mencionamos.

Para mostrar este video, se requieren cookies de terceros. Puede acceder y cambiar sus ajustes de cookies aquí.

El patrón de diseño Factory en un diagrama UML

En el software que se basa en el patrón Factory, el código de un objeto a crear (en este contexto también conocido como producto) se externaliza a una clase aparte. Esta clase abstracta, también llamada “creador” o, siguiendo el patrón, “factoría”, delega la instanciación del objeto a una subclase (ConcreteCreator), la cual finalmente decide qué producto se crea. Con este fin, el ConcreteCreator toma el control del método createProduct() y devuelve un ConcreteProduct, que el creador puede ampliar con código de producción antes de que pase a la interfaz como producto finalizado.

Abajo arrojamos luz sobre el patrón Factory gracias a un diagrama de clase UML que resume de manera gráfica las relaciones y los procesos descritos.

Ventajas e inconvenientes del patrón de diseño Factory

En el Factory Pattern, la llamada del método de programación va totalmente separada de la implementación de clases nuevas, algo que tiene sus ventajas. Por ejemplo, esta condición influye particularmente en cómo puede extenderse el software. Las instancias Factory cuentan con un alto grado de autonomía, lo cual quiere decir que te permiten añadir clases nuevas sin que la aplicación tenga que cambiar de ninguna manera, y todo en paralelo al tiempo de ejecución. En este proceso, basta con implementar la interfaz Factoría e incorporar el creador como corresponda (mediante el ConcreteCreator).

Otra ventaja de este patrón es la comprobabilidad directa de los componentes Factory. Por ejemplo, si un creador pone en marcha tres clases, su funcionalidad puede probarse de manera individual e independiente a la clase a la que se esté apelando. En este último caso, solo hace falta asegurarse de que apele correctamente al creador, incluso si más adelante se extiende el software. Una ventaja adicional es la posibilidad de dar un nombre descriptivo a los métodos Factory (a diferencia del constructor de clase).

En cambio, el inconveniente principal del patrón de diseño Factory es que su implementación conlleva un aumento significativo del número de clases integradas, ya que cada ConcreteProduct requiere un ConcreteCreator. Si bien el enfoque Factory es en principio extremadamente provechoso de cara a la extensión del software, también resulta desventajoso si consideramos el esfuerzo que requiere. Si queremos ampliar una familia de productos, habrá que adaptar como corresponda no solo la interfaz, también todas las clases subordinadas del ConcreteCreator. Por este motivo, es indispensable planificar correctamente y con antelación los tipos de producto necesarios.

Ventajas Inconvenientes
Capacidad de expansión modular de la aplicación Requiere un número elevado de clases
Buena comprobabilidad La extensión de la aplicación es muy elaborada
Nombres de método significativos  

¿Cuándo se utiliza el patrón Factory?

Este patrón de diseño resulta valioso en diversas situaciones. En el software en el que los productos concretos que se crean se desconocen o no se definen con antelación puede ser beneficioso un enfoque alternativo para gestionar las subclases. Los típicos casos en los que se utiliza incluyen marcos o bibliotecas de clases, que se han vuelto prácticamente indispensables como marco básico para el desarrollo de aplicaciones modernas.

Los sistemas de autentificación también se benefician de las ventajas que ofrece el patrón Factory. En lugar de tener una clase central con diversos parámetros que varían en función de la autentificación del usuario, el proceso de autentificación puede delegarse en las clases Factory, que toman decisiones independientes sobre la gestión de cada usuario.

Además, diseñar siguiendo el enfoque del patrón Factory suele valer para cualquier software al que se añadan regularmente clases nuevas acordadas, sobre todo si estas clases tienen que pasar por el mismo proceso de creación.

Ejemplo del patrón Factory (PHP)

El patrón de diseño del Método Factoría puede utilizarse en diversas aplicaciones con lenguajes de programación diferentes. Algunos de los representantes más conocidos son Java, JavaScript, C++, C#, Python, y PHP. Utilizamos este último lenguaje de programación en el siguiente ejemplo práctico, inspirado por una entrada de blog de Phpmonkeys.

En este caso, se crea una situación con la clase abstracta Car (Creador) y la clase Factory CarFactory (ConcreteCreator). La primera se designa de la manera tan sencilla como sea posible y solo contiene código para establecer un color para el coche (color por defecto: blanco) y leerlo.

class Car {
	private $color = null;
	public function __construct() {
		$this->color = "white";
	}
	public function setColor($color) {
		$this->color = $color;
	}
	public function getColor() {
		return $this->color;
	}
}

En la clase Factory, se presentan los métodos para los coches “rojos” (red) y “azules” (blue) así como un método privado para la propia creación de clase:

class CarFactory {
	private function __construct() {
	}
	public static function getBlueCar() {
		return self::getCar("blue");
	}
	public static function getRedCar() {
		return self::getCar("red");
	}
	private static function getCar($color) {
		$car = new Car();
		$car->setColor($color);
		return $car;
	}
}

Gracias al patrón Factory, este método Factory tan claramente dispuesto puede ampliarse con una extensa variedad de funciones adicionales, como otros colores, marcas de coche o precio.

Utilizamos cookies propias y de terceros para mejorar nuestros servicios y mostrarle publicidad relacionada con sus preferencias mediante el análisis de sus hábitos de navegación. Si continua navegando, consideramos que acepta su uso. Puede obtener más información, o bien conocer cómo cambiar la configuración de su navegador en nuestra. Política de Cookies.