
¿Qué son los Factories en PHP y cómo usarlos?
Cuando trabajamos con programación orientada a objetos en PHP, tarde o temprano nos encontramos con la necesidad de crear objetos de manera más flexible, controlada y escalable. Aquí es donde entran los Factories, un patrón de diseño muy útil que nos permite encapsular la lógica de creación de objetos.
¿Qué es un Factory?
Un Factory (o fábrica) es un patrón de diseño creacional que proporciona una forma de crear objetos sin tener que especificar la clase exacta del objeto que se va a crear. En lugar de usar new
directamente en todas partes, centralizamos la lógica de creación en una clase o función dedicada.
Esto es útil, por ejemplo, cuando:
- Queremos desacoplar nuestro código de clases específicas.
- La lógica de creación de objetos es compleja.
- Necesitamos crear distintos tipos de objetos dependiendo de ciertos parámetros.
Ejemplo básico de un Factory
Imaginemos que tenemos una interfaz Vehicle
y dos clases que la implementan: Car
y Motorcycle
.
<?php interface Vehicle { public function move(): void; } class Car implements Vehicle { public function move(): void { echo "El auto se está moviendo"; } } class Motorcycle implements Vehicle { public function move(): void { echo "La motocicleta se está moviendo"; } }
Ahora creamos un factory que se encargue de crear el tipo correcto de vehículo según un parámetro:
<?php class VehicleFactory { public function createVehicle(string $type): Vehicle { if ( $type === 'car' ) { return new Car(); } if ( $type === 'motorcycle' ) { return new Motorcycle(); } throw new InvalidArgumentException("Tipo de vehículo no válido: $type"); } }
Uso del factory
<?php $vehicleFactory = new VehicleFactory(); $myCar = $vehicleFactory->createVehicle('car'); $myCar->move(); // El auto se está moviendo 🚗 $myMoto = $vehicleFactory->createVehicle('motorcycle'); $myMoto->move(); // La motocicleta se está moviendo 🏍️
Ventajas de usar un Factory
- Desacoplamiento: El código que necesita un objeto no tiene que saber cómo se construye exactamente.
- Reutilización: Si necesitas cambiar la lógica de creación, lo haces en un solo lugar.
- Flexibilidad: Puedes devolver subclases distintas o instancias configuradas dinámicamente.
Factory estático
También se puede implementar el patrón como un método estático:
<?php class VehicleFactory { public static function create(string $type): Vehicle { return match($type) { 'car' => new Car(), 'motorcycle' => new Motorcycle(), default => throw new InvalidArgumentException("Tipo no soportado: $type"), }; } } // Uso $vehicle = VehicleFactory::create('car'); $vehicle->move();
Ejemplo más realista: Factory con configuración
En sistemas más complejos, la creación de un objeto puede depender de varios parámetros o incluso de inyecciones de dependencias. Veamos un ejemplo:
<?php class DatabaseConnection { protected string $host; protected string $username; protected string $password; public function __construct(string $host, string $username, string $password) { $this->host = $host; $this->username = $username; $this->password = $password; } public function connect(): void { echo "Conectando a $this->host como $this->username\n"; } } class DatabaseFactory { public function createFromEnv(): DatabaseConnection { return new DatabaseConnection( getenv('DB_HOST'), getenv('DB_USER'), getenv('DB_PASS') ); } } // Uso $dbFactory = new DatabaseFactory(); $dbConnection = $dbFactory->createFromEnv(); $dbConnection->connect();
El patrón Factory es una herramienta poderosa para crear objetos en PHP de manera controlada y flexible. Es especialmente útil en aplicaciones medianas o grandes, donde centralizar la lógica de instanciación te ayuda a mantener el código más limpio, desacoplado y fácil de mantener.