Patrón Factory
Parte de la sección Programación Orientada a Objetos del Journey de C# de Coddy. Lección 53 de 70.
El patrón Factory es un patrón creacional que delega la creación de objetos a un método o una clase independientes. En lugar de usar new directamente en tu código, le pides a una fábrica que cree objetos por ti. Esto centraliza la lógica de creación y hace que tu código sea más flexible.
Considera un escenario en el que necesitas crear diferentes tipos de documentos. Sin una fábrica, tu código queda estrechamente acoplado a clases específicas:
// Sin Factory - lógica de creación dispersa
IDocument doc;
if (type == "pdf")
doc = new PdfDocument();
else if (type == "word")
doc = new WordDocument();Una fábrica encapsula esta toma de decisiones en un solo lugar:
public interface IDocument
{
void Open();
}
public class PdfDocument : IDocument
{
public void Open() => Console.WriteLine("Opening PDF");
}
public class WordDocument : IDocument
{
public void Open() => Console.WriteLine("Opening Word");
}
public class DocumentFactory
{
public IDocument Create(string type)
{
return type switch
{
"pdf" => new PdfDocument(),
"word" => new WordDocument(),
_ => throw new ArgumentException("Unknown type")
};
}
}Ahora el código del cliente simplemente solicita lo que necesita sin conocer las clases concretas:
var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open(); // Abriendo PDFEl patrón Factory destaca cuando necesitas añadir nuevos tipos más adelante. Añadir un SpreadsheetDocument requiere cambios únicamente en la fábrica, no en todos los lugares donde se crean documentos. Esta separación facilita el mantenimiento y las pruebas de tu base de código.
Desafío
FácilConstruyamos un sistema de notificaciones usando el patrón Factory. En lugar de crear directamente distintos tipos de notificación por todo tu código, centralizarás la lógica de creación en una clase fábrica que decide qué notificación crear basándose en un identificador de cadena sencillo.
Organizarás tu código en tres archivos:
Notification.cs: Define una interfazINotificationen el espacio de nombresNotificationscon un único métodoSend(string message)que devuelve una cadena. Después crea tres clases que implementen esta interfaz:EmailNotification- devuelve"Email: {message}"SmsNotification- devuelve"SMS: {message}"PushNotification- devuelve"Push: {message}"
NotificationFactory.cs: Crea una claseNotificationFactoryen el mismo espacio de nombres con un métodoCreate(string type)que devuelve elINotificationadecuado según la cadena de tipo:"email"devuelve unEmailNotification"sms"devuelve unSmsNotification"push"devuelve unPushNotification
EmailNotificationcomo valor predeterminado.Program.cs: Reúne todo creando una instancia de la fábrica y utilizándola para crear notificaciones según la entrada. La fábrica se encarga de toda la toma de decisiones sobre qué clase concreta instanciar.
Recibirás dos entradas:
- El tipo de notificación (por ejemplo,
sms) - El mensaje que se enviará (por ejemplo,
Your order has shipped)
Usa tu fábrica para crear el tipo de notificación adecuado, después llama a su método Send con el mensaje e imprime el resultado.
Por ejemplo, si las entradas son push y Meeting in 5 minutes, la salida debería ser:
Push: Meeting in 5 minutesObserva que tu código principal nunca usa new EmailNotification() ni algo similar: simplemente le pide a la fábrica lo que necesita. Si más adelante añades una SlackNotification, ¡solo tendrías que actualizar la fábrica, no todos los lugares que crean notificaciones!
Pruébalo tú mismo
using System;
using Notifications;
class Program
{
public static void Main(string[] args)
{
// Leer la entrada
string type = Console.ReadLine();
string message = Console.ReadLine();
// TODO: Crea una instancia de NotificationFactory
// TODO: Usa la factory para crear la notificación apropiada
// TODO: Llama al método Send e imprime el resultado
}
}
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 externosNamespaces y directivasIntro a clases y objetosLa palabra clave 'this'Métodos y parámetrosCampos vs PropiedadesConstructoresInicializadores de objetosResumen - Calculadora simple4Herencia
Sintaxis básica de herencia (:)La palabra clave 'base'Palabras clave Virtual y OverrideClases selladas (Sealed)La clase base 'object'Resumen: Jerarquía de empleados7Características avanzadas
Sobrecarga de operadoresIndexadores (this[])Sobrescritura de ToString()Métodos de extensiónResumen - Lista personalizada10Patrones de diseño - Parte 1
Introducción a los patrones de diseñoSingleton Thread-SafePatrón FactoryPatrón Observer (Eventos)Patrón Strategy2Propiedades y miembros estáticos
Propiedades autoimplementadasPropiedades de solo lectura y escrituraCampos y métodos estáticosClases estáticasMiembros con cuerpo de expresión5Polimorfismo e Interfaces
Polimorfismo: Compilación vs. EjecuciónInterfaz vs. Clase AbstractaInterfaces MúltiplesInterfaces ExplícitasUpcasting y DowncastingRepaso: Calculadora de Figuras8Conceptos avanzados de POO
Composición sobre herenciaGenéricos (clases y métodos)Delegados y eventosAtributos y ReflexiónIDisposable y la sentencia usingFundamentos de Inyección de dependencias11Patrones de diseño, parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón Composite3Arquitectura de clases
Datos de instancia vs. estáticosPalabras clave 'readonly' y 'const'Campos de respaldoResumen - Gestor de cuentas bancarias6Encapsulamiento
Modificadores de accesoPropiedades para el encapsulamientoImplementación de ocultamiento de datosPatrones de inmutabilidadRepaso - Registros de estudiantesPractica por tu cuenta: Compilador de C# online