Patrón Factory
Parte de la sección Programación Orientada a Objetos del Journey de Java de Coddy — lección 66 de 87.
El Patrón Factory es un patrón de diseño creacional que delega la creación de objetos a un método o clase independiente. En lugar de usar new directamente en tu código, le pides a una fábrica que cree objetos por ti. Esto es especialmente útil cuando tienes múltiples clases relacionadas que comparten una interfaz o padre común.
Considere un sistema de notificaciones que puede enviar correos electrónicos, SMS o notificaciones push. Sin una fábrica, su código necesitaría conocer cada clase concreta:
// Sin Factory - el cliente debe conocer todas las clases concretas
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Con el Patrón Factory, centralizas esta lógica de creación:
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}Ahora el código del cliente es más limpio y no depende de clases concretas:
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Salida: Email: Hello!El beneficio clave es que agregar nuevos tipos de notificación solo requiere actualizar la fábrica; el código del cliente permanece sin cambios. Esto sigue el principio de programar para una interfaz, lo que hace que su sistema sea más flexible y fácil de extender.
Desafío
Fácil¡Vamos a construir un sistema de dibujo de formas utilizando el Patrón Factory! En lugar de crear objetos de forma directamente en todo tu código, centralizarás la lógica de creación en una fábrica que produce diferentes tipos de formas basadas en un identificador de cadena simple.
Organizarás tu código en cuatro archivos:
Shape.java: Define una interfaz llamadaShapeque sirva como el contrato común para todas las formas. Tu interfaz debe declarar un único métododraw()que no devuelva nada pero imprima información sobre la forma que se está dibujando.Shapes.java: Crea tres clases que implementen tu interfazShape:Circle- su métododraw()debe imprimirDrawing a CircleRectangle- su métododraw()debe imprimirDrawing a RectangleTriangle- su métododraw()debe imprimirDrawing a TriangleShapeFactory.java: Crea la clase de fábrica que maneja la creación de formas. TuShapeFactorydebe tener un método estáticocreateShape(String type)que devuelva unShape. Basado en el parámetro type:- Si type es igual a
"circle", devuelve un nuevoCircle - Si type es igual a
"rectangle", devuelve un nuevoRectangle - Si type es igual a
"triangle", devuelve un nuevoTriangle - Para cualquier otro valor, devuelve
null
- Si type es igual a
Main.java: ¡Une tu sistema de fábrica! Recibirás dos entradas: dos tipos de formas (ambas Strings).Para cada entrada, usa tu
ShapeFactorypara crear la forma y almacénala en una variableShape. Si la fábrica devuelve una forma válida (no nula), llama a su métododraw(). Si devuelve nulo, imprimeUnknown shape: [type]donde [type] es la entrada que se proporcionó.Procesa ambas entradas en orden, cada una en su propia línea de salida.
Recibirás dos entradas en orden: el primer tipo de forma (String) y el segundo tipo de forma (String).
Observa cómo tu clase Main nunca usa new Circle() o new Rectangle() directamente; solo conoce la interfaz Shape y le pide a la fábrica que cree los objetos. ¡Este es el poder del Patrón Factory: el código del cliente está desacoplado de las clases concretas!
Hoja de referencia
El Patrón Factory es un patrón de diseño creacional que delega la creación de objetos a un método o clase independiente, centralizando la lógica de creación y desacoplando el código del cliente de las implementaciones concretas.
En lugar de instanciar objetos directamente con new, se utiliza un método de fábrica:
// Sin Factory - el cliente depende de clases concretas
Notification notification;
if (type.equals("email")) {
notification = new EmailNotification();
} else if (type.equals("sms")) {
notification = new SMSNotification();
}Con el Patrón Factory, defina una interfaz común e implementaciones concretas:
public interface Notification {
void send(String message);
}
public class EmailNotification implements Notification {
public void send(String message) {
System.out.println("Email: " + message);
}
}
public class SMSNotification implements Notification {
public void send(String message) {
System.out.println("SMS: " + message);
}
}Cree una clase de fábrica con un método de creación estático:
public class NotificationFactory {
public static Notification create(String type) {
if (type.equals("email")) {
return new EmailNotification();
} else if (type.equals("sms")) {
return new SMSNotification();
}
return null;
}
}El código del cliente utiliza la fábrica en lugar de la instanciación directa:
Notification notification = NotificationFactory.create("email");
notification.send("Hello!"); // Salida: Email: Hello!Beneficios: Agregar nuevos tipos solo requiere actualizar la fábrica; el código del cliente permanece sin cambios. Esto sigue el principio de programar para una interfaz, lo que hace que los sistemas sean más flexibles y fáciles de extender.
Pruébalo tú mismo
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lee dos tipos de formas
String type1 = scanner.nextLine();
String type2 = scanner.nextLine();
// TODO: Usa ShapeFactory para crear la primera forma
// Si la forma no es null, llama a draw()
// Si la forma es null, imprime "Unknown shape: [type]"
// TODO: Haz lo mismo para la segunda forma
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1Fundamentos de OOP
Archivos externosIntroducción a la OOPClases vs. ObjetosLa palabra clave thisMétodosCampos (Atributos)Método constructorSobrecarga de constructoresResumen - Calculadora simple4Herencia
Herencia básica (extends)La palabra clave superSobrescritura de métodos (@Override)Encadenamiento de constructoresLa clase ObjectHerencia simple y multinivelPor qué no hay herencia múltiple de clasesResumen - Jerarquía de empleados7Métodos especiales y la clase Object
Método toString()equals() y hashCode()Método clone()compareTo() y ComparableInterfaz ComparatorResumen - Ordenamiento personalizado2Modificadores de acceso y encapsulamiento
Visión general de los niveles de accesoMétodos Getter y SetterOcultamiento de informaciónLa palabra clave finalResumen - Gestor de cuentas bancarias5Polimorfismo
Fundamentos de sobrecarga de métodosSobrescritura de métodos (tiempo de ejecución)Upcasting y DowncastingEl operador instanceofClases y métodos abstractosResumen - Calculadora de figuras8Conceptos avanzados de POO
Composición vs. HerenciaAgregación vs. ComposiciónClases internas, anidadas y anónimasEnums y métodos de EnumRecords (Java 16+)Clases selladas (Java 17+)11Patrones de diseño - Parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón BuilderPatrón ObserverPatrón Strategy3Propiedades de clase y miembros estáticos
Variables de instancia vs. estáticasMétodos estáticosBloques estáticosConstantes (static final)Repaso - Contador y utilidad6Interfaces y Clases Abstractas
Introducción a las InterfacesImplementación de InterfacesImplementación de Múltiples InterfacesMétodos Default y Static en InterfacesClases Abstractas vs InterfacesInterfaces FuncionalesResumen - Sistema de Pagos9Genéricos
Introducción a los genéricosClases genéricasMétodos genéricosParámetros de tipo delimitadosComodines (?, extends, super)Resumen - Contenedor genérico12Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Iterator