¡Hola amigo! Hoy continuaremos estudiando patrones de diseño contigo. En esta conferencia hablaremos de la Fábrica. Discutiremos con usted qué problema se resuelve usando esta plantilla y veremos un ejemplo de cómo una fábrica ayuda a abrir una cafetería. Y también te daré 5 sencillos pasos para crear una fábrica. Para estar en sintonía con todos y captar fácilmente la esencia, debe estar familiarizado con los siguientes temas:
- Herencia en Java
- Reducir y expandir tipos de referencia en Java
- Interacción entre diferentes clases y objetos.
¿Qué es una fábrica?
El patrón de diseño Factory le permite controlar la creación de objetos. El proceso de creación de un nuevo objeto no es tan sencillo, pero tampoco demasiado complicado. Todos sabemos que para crear un nuevo objeto debemos utilizar el archivonew
. Y puede parecer que aquí no hay nada que gestionar, pero no es así. Pueden surgir dificultades cuando nuestra aplicación tiene una determinada clase que tiene muchos descendientes, y es necesario crear una instancia de una determinada clase dependiendo de algunas condiciones. Factory es un patrón de diseño que ayuda a resolver el problema de crear diferentes objetos dependiendo de algunas condiciones. Abstracto, ¿no? Aparecerá más especificidad y claridad cuando veamos el siguiente ejemplo.
Creamos diferentes tipos de café.
Digamos que queremos automatizar una cafetería. Necesitamos aprender a preparar diferentes tipos de café. Para ello, en nuestra aplicación crearemos una clase de café y sus derivados: americano, capuchino, espresso, latte, esos tipos de café que prepararemos. Empecemos con la clase de café general:public class Coffee {
public void grindCoffee(){
// перемалываем кофе
}
public void makeCoffee(){
// делаем кофе
}
public void pourIntoCup(){
// наливаем в чашку
}
}
A continuación, creemos sus herederos:
public class Americano extends Coffee {}
public class Cappuccino extends Coffee {}
public class CaffeLatte extends Coffee {}
public class Espresso extends Coffee {}
Nuestros clientes pedirán algún tipo de café y esta información debe pasarse al programa. Esto se puede hacer de diferentes maneras, por ejemplo usando String
. Pero es el más adecuado para estos fines enum
. Creemos enum
y definamos en él los tipos de café de los que aceptamos pedidos:
public enum CoffeeType {
ESPRESSO,
AMERICANO,
CAFFE_LATTE,
CAPPUCCINO
}
Genial, ahora escribamos el código para 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("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
El método orderCoffee
se puede dividir en dos componentes:
- Creando una instancia de café específica en un bloque
switch-case
. Aquí es donde lo que hace la Fábrica es la creación de un tipo específico dependiendo de las condiciones. - La preparación en sí se muele, se cuece y se vierte en una taza.
- El algoritmo de preparación en sí (moler, cocinar y verter en una taza) permanecerá sin cambios (al menos eso esperamos).
- Pero la gama de cafés puede cambiar. Quizás empecemos a hacer mocha... Mocha... Mokkachi... Dios lo bendiga, un nuevo tipo de café.
switch-case
. También es posible que en nuestra cafetería el método orderCoffee
no sea el único lugar en el que creemos diferentes tipos de café. Por lo tanto, será necesario realizar cambios en varios lugares. Probablemente ya entiendas a qué me refiero. Necesitamos refactorizar. Mueva el bloque responsable de crear café a una clase separada por dos razones:
- Podremos reutilizar la lógica de crear café en otros lugares.
- Si el rango cambia, no tendremos que editar el código en todos los lugares donde se utilizará la creación de café. Bastará con cambiar el código en un solo lugar.
Estamos aserrando nuestra primera fábrica.
Para ello, creemos una nueva clase que se encargará únicamente de crear las instancias necesarias de 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 Factory en su forma más simple. Aunque todo podría ser aún más sencillo si el método se volviera createCoffee
estático. Pero entonces perderíamos dos posibilidades:
- Hereda
SimpleCoffeeFactory
y anula elcreateCoffee
. - Implementar la implementación de fábrica requerida en nuestras clases.
Introducción de una fábrica en una cafetería.
Reescribamos nuestra 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("Вот ваш кофе! Спасибо, приходите еще!");
return coffee;
}
}
Excelente. Ahora intentemos describir de forma esquemática y concisa la estructura del patrón de diseño Factory.
5 pasos para abrir tu propia fábrica
Paso 1. En tu programa tienes una clase con varios descendientes, como en la siguiente imagen: Paso 2. Creas una claseenum
en la que defines una variable enum para cada clase descendiente:
enum CatType {
LION,
TIGER,
BARSIK
}
Paso 3. Construyes tu fábrica. Lo llamas MyClassFactory
, el código está a continuación:
class CatFactory {}
Paso 4. Creas un método en tu fábrica createMyClass
que toma la variable - enum
MyClassType
. Código a continuación:
class CatFactory {
public Cat createCat(CatType type) {
}
}
Paso 5. Escribes un bloque en el cuerpo del método switch-case
en el que iteras a través de todos los valores de enumeración y creas una instancia de la clase correspondiente al enum
valor:
class CatFactory {
public Cat createCat(CatType type) {
Cat cat = null;
switch (type) {
case LION:
cat = new Barsik();
break;
case TIGER:
cat = new Tiger();
break;
case BARSIK:
cat = new Lion();
break;
}
return cat;
}
}
Como un jefe.
GO TO FULL VERSION