Patrón Factory
Parte de la sección Programación Orientada a Objetos del Journey de PHP de Coddy. Lección 72 de 91.
El patrón Factory es un patrón de diseño creacional que delega la creación de objetos a una clase o método independiente. En lugar de usar new directamente en todo tu código, le pides a una fábrica que cree los objetos por ti.
Este patrón es especialmente útil cuando tienes varias clases relacionadas que comparten una interfaz común y quieres decidir cuál instanciar en función de alguna condición. Considera un sistema de notificaciones que puede enviar mensajes a través de distintos canales:
<?php
interface Notification {
public function send(string $message): string;
}
class EmailNotification implements Notification {
public function send(string $message): string {
return "Email: $message";
}
}
class SmsNotification implements Notification {
public function send(string $message): string {
return "SMS: $message";
}
}
Sin una fábrica, dispersarías instrucciones if y llamadas a new por todas partes. La fábrica centraliza esta lógica:
<?php
class NotificationFactory {
public static function create(string $type): Notification {
return match($type) {
'email' => new EmailNotification(),
'sms' => new SmsNotification(),
default => throw new InvalidArgumentException("Unknown type: $type")
};
}
}
$notification = NotificationFactory::create('email');
echo $notification->send('Hello!');
Salida:
Email: Hello!El beneficio clave es que tu código depende de la interfaz Notification, no de clases concretas. Si más adelante añades una clase PushNotification, solo actualizas la fábrica. Todo el código que utiliza la fábrica obtiene automáticamente acceso al nuevo tipo sin modificaciones.
Desafío
FácilConstruyamos un sistema generador de documentos utilizando el patrón Factory. Los distintos tipos de documentos (PDF, HTML, texto sin formato) comparten una interfaz común, pero producen resultados diferentes: un escenario perfecto para centralizar la creación de objetos en una fábrica.
Organizarás tu código en cuatro archivos:
Document.php: Crea una interfazDocumentque define el contrato que deben seguir todos los tipos de documentos. Debe tener un único métodorender(string $content): stringque recibe contenido y devuelve el resultado del documento con formato.Documents.php: Incluye la interfaz Document y crea tres clases que la implementen:PdfDocument: Su métodorender()devuelve"PDF: [content]"HtmlDocument: Su métodorender()devuelve"<html>[content]</html>"TextDocument: Su métodorender()devuelve"TXT: [content]"
DocumentFactory.php: Incluye el archivo Documents y crea una claseDocumentFactorycon un método estáticocreate(string $type): Document. Este método debe usarmatchpara devolver el objeto de documento adecuado según el tipo:"pdf"devuelve un nuevoPdfDocument"html"devuelve un nuevoHtmlDocument"text"devuelve un nuevoTextDocument- Cualquier otro tipo debe lanzar una
InvalidArgumentExceptioncon el mensaje"Unknown document type: [type]"
main.php: Incluye el archivo DocumentFactory. Recibirás dos entradas: un tipo de documento y el contenido que se va a renderizar.Usa la fábrica para crear el tipo de documento adecuado, después llama a su método
render()con el contenido e imprime el resultado.En una línea nueva, imprime
"Factory benefit: Adding new types only requires updating the factory"para destacar por qué este patrón es valioso.
El patrón Factory mantiene tu código flexible; cuando necesites añadir posteriormente un MarkdownDocument, solo tendrás que actualizar la fábrica, mientras que todo el código existente seguirá funcionando sin cambios.
Pruébalo tú mismo
<?php
require_once 'DocumentFactory.php';
// Leer la entrada
$type = trim(fgets(STDIN));
$content = trim(fgets(STDIN));
// TODO: Usa DocumentFactory para crear el tipo de documento apropiado
// TODO: Llama al método render() con el contenido e imprime el resultado
// TODO: On a new line, print "Factory benefit: Adding new types only requires updating the factory"
?>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 la POO
Archivos externosIntroducción a la POOClases frente a objetosLa palabra clave $thisMétodosPropiedadesConstructor (__construct)Destructor (__destruct)Repaso: calculadora simple4Herencia
Herencia básicaLa palabra clave parent::Sobrescritura de métodosLa palabra clave finalClases abstractasRepaso - Jerarquía de empleados7Encapsulación
Público, protegido, privadoModificadores de acceso en profundidadGetters y settersOcultación de la informaciónPromoción del constructor (8.0)Repaso: sistema de registros de estudiantes10Conceptos avanzados de OOP
Composición vs. herenciaInyección de dependenciasClases anónimasEnums (PHP 8.1)Fibras (PHP 8.1)Análisis profundo de la clonación de objetosGeneradores e iteradores13Patrones de diseño Parte 2
Patrón CommandPatrón AdapterPatrón DecoratorPatrón Template MethodPatrón StatePatrón CompositePatrón Repository2Namespaces y carga automática
Introducción a los NamespacesLa palabra clave useEstándar de carga automática PSR-4Autoloader de ComposerRepaso: proyecto organizado5Interfaces y contratos
Introducción a las interfacesImplementación de interfacesImplementación de múltiples interfacesInterfaces vs. clase abstractaTipado con interfacesRepaso - Calculadora de formas8Métodos mágicos
Introducción a los métodos mágicos__toString y __debugInfo__get, __set, __isset, __unset__call y __callStatic__clone y clonación de objetos__serialize y __unserializeRepaso: colección personalizada3Propiedades de clase
Propiedades de instancia vs. estáticasConstantes en clasesMétodos y propiedades estáticosPropiedades privadas y protegidasPropiedades de solo lectura (PHP 8.1)Repaso: gestor de cuentas bancarias6Polimorfismo
Repaso de la sobrescritura de métodosPolimorfismo mediante interfacesAnotaciones de tipo y tipos uniónEnlace estático tardíoRepaso: procesador de pagos9Traits
Introducción a los TraitsUso de múltiples TraitsResolución de conflictos entre TraitsMétodos abstractos en TraitsTraits frente a la herencia12Patrones de diseño, parte 1
Introducción a los patrones de diseñoPatrón SingletonPatrón FactoryPatrón ObserverPatrón StrategyPractica por tu cuenta: Compilador de PHP online