Patrón Factory Method
El herrero que forja héroes ⚔️🔥
💾 Continuamos nuestra serie de Patrones de Diseño explicados con ejemplos (un poco frikis) 👾
En esta entrega nos adentramos en la forja del código, donde los objetos no nacen por arte de magia, sino gracias al sabio Herrero de la Factoría.
⚙️ El problema: cuando tu código fabrica demasiado
Imagina que estás creando un juego de rol y necesitas generar distintos tipos de héroes:
- un Guerrero para el combate cuerpo a cuerpo,
- un Arquero para los ataques a distancia,
- y un Mago para lanzar hechizos arcanos.
Podrías crear cada uno directamente con new… pero si el código empieza a decidir cómo crear cada héroe, terminarás con una mazmorra de if y switch.
💀 Ejemplo erróneo
<?php
class Heroe {
public $nombre;
public $arma;
public function __construct($nombre, $arma) {
$this->nombre = $nombre;
$this->arma = $arma;
}
public function atacar() {
echo "{$this->nombre} ataca con {$this->arma}!\n";
}
}
class Juego {
public function crearHeroe($tipo) {
if ($tipo === "guerrero") {
return new Heroe("Guerrero", "espada");
} elseif ($tipo === "arquero") {
return new Heroe("Arquero", "arco");
} elseif ($tipo === "mago") {
return new Heroe("Mago", "hechizo de fuego");
}
}
}
$juego = new Juego();
$heroe = $juego->crearHeroe("mago");
$heroe->atacar();
👉 Problema:
Si mañana quieres añadir un Paladín, tendrás que editar Juego, rompiendo el principio de abierto/cerrado.
El herrero está haciendo todo el trabajo, y eso no escala ⚒️
🧠 La solución: delega la forja a cada tipo de taller
El Patrón Factory Method nos enseña a dejar que cada subclase decida cómo fabricar su héroe.
El código principal no necesita saber los detalles de la creación.
✅ Ejemplo correcto con Factory Method
<?php
interface Heroe {
public function atacar();
}
class Guerrero implements Heroe {
public function atacar() {
echo "⚔️ El Guerrero golpea con su espada!\n";
}
}
class Arquero implements Heroe {
public function atacar() {
echo "🏹 El Arquero dispara una flecha!\n";
}
}
class Mago implements Heroe {
public function atacar() {
echo "🔥 El Mago lanza un hechizo de fuego!\n";
}
}
// --- La fábrica base ---
abstract class FabricaDeHeroes {
abstract public function crearHeroe(): Heroe;
public function prepararHeroe() {
$heroe = $this->crearHeroe();
echo "✨ Se ha forjado un nuevo héroe...\n";
return $heroe;
}
}
// --- Fábricas concretas ---
class FabricaGuerrero extends FabricaDeHeroes {
public function crearHeroe(): Heroe {
return new Guerrero();
}
}
class FabricaArquero extends FabricaDeHeroes {
public function crearHeroe(): Heroe {
return new Arquero();
}
}
class FabricaMago extends FabricaDeHeroes {
public function crearHeroe(): Heroe {
return new Mago();
}
}
// --- Cliente ---
$fabricas = [
new FabricaGuerrero(),
new FabricaArquero(),
new FabricaMago(),
];
foreach ($fabricas as $fabrica) {
$heroe = $fabrica->prepararHeroe();
$heroe->atacar();
}
⚔️ Resultado
✨ Se ha forjado un nuevo héroe...
⚔️ El Guerrero golpea con su espada!
✨ Se ha forjado un nuevo héroe...
🏹 El Arquero dispara una flecha!
✨ Se ha forjado un nuevo héroe...
🔥 El Mago lanza un hechizo de fuego!
🧩 Qué conseguimos
✅ Separación de responsabilidades – el juego no decide cómo se crean los héroes.
✅ Extensibilidad – puedes añadir nuevas fábricas sin tocar el código existente.
✅ Código más limpio y reutilizable – el herrero trabaja con disciplina OOP 😎
🧙♂️ En resumen
El Patrón Factory Method es como tener un maestro herrero en tu proyecto: tú solo le pides el héroe que necesitas, y él se encarga de forjarlo sin romper nada.
Eso ha sido todo por hoy.
Nos vemos en el próximo patrón... o en la próxima frikada que se me ocurra para explicarlo ⚒️🔥