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 una clase separados. En lugar de usar new directamente en tu código, le pides a una fábrica que cree objetos por ti. Esto resulta especialmente útil cuando tienes varias clases relacionadas que comparten una interfaz o una clase principal común.
Considera un sistema de notificaciones que puede enviar correos electrónicos, SMS o notificaciones push. Sin una fábrica, tu código tendría que 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 principal es que añadir 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 tu sistema sea más flexible y fácil de ampliar.
Desafío
Fácil¡Construyamos un sistema de dibujo de figuras usando el patrón Factory! En lugar de crear objetos de figuras directamente a lo largo de tu código, centralizarás la lógica de creación en una fábrica que produce diferentes tipos de figuras basándose en un identificador de cadena simple.
Organizarás tu código en cuatro archivos:
Shape.java: Define una interfaz llamadaShapeque sirva como contrato común para todas las figuras. Tu interfaz debe declarar un único métododraw()que no devuelva nada, sino que imprima información sobre la figura 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 fábrica que gestione la creación de figuras. TuShapeFactorydebe tener un método estáticocreateShape(String type)que devuelva unShape. Según el parámetro type:- Si type es igual a
"circle", devuelve unCirclenuevo - Si type es igual a
"rectangle", devuelve unRectanglenuevo - Si type es igual a
"triangle", devuelve unTrianglenuevo - Para cualquier otro valor, devuelve
null
- Si type es igual a
Main.java: ¡Integra tu sistema de fábrica! Recibirás dos entradas: dos tipos de figuras (ambos String).Para cada entrada, usa tu
ShapeFactorypara crear la figura y guárdala en una variableShape. Si la fábrica devuelve una figura válida (no null), llama a su métododraw(). Si devuelve null, imprimeUnknown shape: [type], donde [type] es la entrada proporcionada.Procesa ambas entradas en orden, cada una en su propia línea de salida.
Recibirás dos entradas en orden: el primer tipo de figura (String) y el segundo tipo de figura (String).
Observa que tu clase Main nunca usa new Circle() ni new Rectangle() directamente. Solo conoce la interfaz Shape y le pide a la fábrica que cree objetos. ¡Este es el poder del patrón Factory: el código cliente está desacoplado de las clases concretas!
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()
// If the shape is null, print "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 IteratorPractica por tu cuenta: Compilador de Java online