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 de creación 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 los objetos por ti. Esto centraliza la lógica de creación y hace que tu código sea más flexible.
Considere un escenario en el que necesita crear diferentes tipos de documentos. Sin una fábrica, su código se vuelve 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 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 solo en la fábrica, no en todos los lugares donde se crean documentos. Esta separación hace que tu base de código sea más fácil de mantener y probar.
Desafío
FácilVamos a construir un sistema de notificaciones utilizando el patrón Factory. En lugar de crear diferentes tipos de notificaciones directamente en todo el código, centralizarás la lógica de creación en una clase de fábrica que decide qué notificación crear basándose en un identificador de cadena simple.
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. Luego 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 elINotificationapropiado basado en la cadena de tipo:"email"devuelve unEmailNotification"sms"devuelve unSmsNotification"push"devuelve unPushNotification
EmailNotificationpor defecto.Program.cs: Une todo creando una instancia de la fábrica y usándola para crear notificaciones basadas en 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 a enviar (por ejemplo,
Your order has shipped)
Usa tu fábrica para crear el tipo de notificación apropiado, luego 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 cómo tu código principal nunca usa new EmailNotification() o similares; simplemente le pide a la fábrica lo que necesita. Si más adelante añades un SlackNotification, ¡solo tendrías que actualizar la fábrica, no cada lugar donde se crean notificaciones!
Hoja de referencia
El patrón Factory es un patrón de creación que delega la creación de objetos a un método o clase independiente, centralizando la lógica de creación y haciendo que el código sea más flexible.
Sin una fábrica, la creación de objetos está dispersa y estrechamente acoplada:
// Sin Factory - lógica de creación dispersa
IDocument doc;
if (type == "pdf")
doc = new PdfDocument();
else if (type == "word")
doc = new WordDocument();Con una fábrica, la lógica de creación se encapsula 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")
};
}
}El código del cliente solicita objetos sin conocer las clases concretas:
var factory = new DocumentFactory();
IDocument doc = factory.Create("pdf");
doc.Open(); // Opening PDFEl patrón Factory facilita la adición de nuevos tipos: los cambios se aíslan en la fábrica, en lugar de estar dispersos por toda la base de código.
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: Crear una instancia de NotificationFactory
// TODO: Usar la fábrica para crear la notificación adecuada
// TODO: Llamar al método Send e imprimir 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 estudiantes