¡Hola amigo! Hoy continuaremos estudiando patrones de diseño. En esta lección, vamos a hablar sobre las fábricas. Discutiremos el problema que resuelve este patrón y veremos un ejemplo de cómo una fábrica puede ayudarlo a abrir una cafetería. Además, te daré 5 pasos simples para crear una fábrica.
Para asegurarse de que todos estamos en la misma longitud de onda y que comprenderá rápidamente este concepto, debe estar familiarizado con los siguientes temas:
Paso 2. Crea un

- Herencia en Java
- Estrechamiento y ampliación de tipos de referencia en Java
- Interacción entre diferentes clases y objetos.
¿Qué es una fábrica?
El patrón de diseño de fábrica le permite controlar la creación de objetos. El proceso de creación de un nuevo objeto no es súper simple, pero tampoco demasiado complicado. Todos sabemos que necesitamos elnew
operador para crear un nuevo objeto. Quizás parezca que aquí no hay nada que controlar, pero eso no es cierto. Supongamos que nuestra aplicación tiene una cierta clase que tiene muchos descendientes. Pueden surgir dificultades cuando es necesario crear una instancia de una clase específica dependiendo de ciertas condiciones. Una fábrica es un patrón de diseño que ayuda a resolver el problema de crear varios objetos dependiendo de ciertas condiciones. ¿Cómo es eso para un concepto abstracto? Esto se volverá más claro y más específico cuando veamos el siguiente ejemplo.
Preparemos varios tipos de café.
Supongamos que queremos automatizar una cafetería. Necesitamos enseñar a nuestro programa cómo hacer diferentes tipos de café. Para ello, crearemos una clase de café y algunas clases derivadas para representar los tipos de café que prepararemos: americano, capuchino, espresso y latte. Comencemos con una clase general de café:public class Coffee {
public void grindCoffee(){
// Grind the coffee
}
public void makeCoffee(){
// Brew the coffee
}
public void pourIntoCup(){
// Pour into a cup
}
}
A continuación, crearemos sus clases secundarias:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Nuestros clientes pueden pedir cualquier tipo de café. Sus órdenes deben pasarse al programa. Esto se puede hacer de muchas maneras, por ejemplo, usando String
. Pero un enum
es mejor para esto. Crearemos enum
y definiremos campos de enumeración que correspondan a los tipos de café que se pueden pedir:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Excelente. Ahora escribamos el código de nuestra cafetería:
public class CoffeeShop {
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucсino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
El orderCoffee
método se puede dividir en dos partes:
- Creación de una instancia específica de café en una
switch
declaración. Aquí es donde una fábrica hace lo que hace: crear un tipo específico según las condiciones. - Preparación: se trata de moler, preparar y verter en una taza.
- Los pasos involucrados en la preparación en sí (moler, colar y verter en una taza) permanecerán sin cambios (al menos contamos con esto).
- Pero la variedad de cafés puede cambiar. Tal vez empecemos a hacer moka... Frappu... Mochacci... Lo que sea, un nuevo tipo de café.
switch
declaración del método. También es posible que en nuestra cafetería el orderCoffee
método no sea el único lugar donde crearemos diferentes tipos de café. Como resultado, habrá que hacer cambios en varios lugares. Probablemente ya entiendas a lo que me refiero. Necesitamos refactorizar. Mueva el bloque responsable de crear café a una clase separada por dos razones:
- Podemos reutilizar la lógica de hacer café en otros lugares.
- Si el surtido cambia, no tendremos que editar el código en todos los lugares donde se crea el café. Bastará con cambiar nuestro código en un solo lugar.
Montando nuestra primera fábrica
Para ello, crearemos una nueva clase que solo se encargará de crear las instancias necesarias de las clases de café:public class SimpleCoffeeFactory {
public Coffee createCoffee(CoffeeType type) {
Coffee coffee = null;
switch (type) {
case AMERICANO:
coffee = new Americano();
break;
case ESPRESSO:
coffee = new Espresso();
break;
case CAPPUCCINO:
coffee = new Cappucino();
break;
case CAFFE_LATTE:
coffee = new CaffeLatte();
break;
}
return coffee;
}
}
¡Felicidades! Acabamos de implementar el patrón de diseño de fábrica en su forma más simple (casi). Podría haber sido aún más simple si hubiéramos hecho el createCoffee
método estático. Pero entonces perderíamos dos capacidades:
- La capacidad de heredar
SimpleCoffeeFactory
y anular elcreateCoffee
método. - La capacidad de agregar la implementación de fábrica requerida a nuestras clases.
Añadir una fábrica a la cafetería.
Reescribamos la clase de cafetería usando una fábrica:public class CoffeeShop {
private final SimpleCoffeeFactory coffeeFactory;
public CoffeeShop(SimpleCoffeeFactory coffeeFactory) {
this.coffeeFactory = coffeeFactory;
}
public Coffee orderCoffee(CoffeeType type) {
Coffee coffee = coffeeFactory.createCoffee(type);
coffee.grindCoffee();
coffee.makeCoffee();
coffee.pourIntoCup();
System.out.println("Here's your coffee! Thanks! Come again!");
return coffee;
}
}
Excelente. Ahora proporcionaremos una descripción concisa de la estructura general del patrón de diseño de fábrica.
5 pasos para abrir tu propia fábrica
Paso 1. Su programa tiene una clase con varios descendientes, como en el siguiente diagrama:
enum
con un campo para cada clase secundaria:
enum CatType {
LION,
TIGER,
FLUFFY
}
Paso 3. Construye tu fábrica. Llámalo CatFactory
_ Aquí está el código:
class CatFactory {}
Paso 4. En su fábrica, cree un createCat
método que tome un CatType
argumento. Aquí está el código:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Paso 5. En el cuerpo del método, escriba una switch
declaración que enumere los campos de enumeración y cree una instancia de la clase que corresponda al enum
valor pasado:
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Fluffy();
break;
case TIGER:
cat = new Tiger();
break;
case FLUFFY:
cat = new Lion();
break;
}
return cat;
}
}
Ahora puedes dirigir una fábrica como un jefe. :)
GO TO FULL VERSION