Patrones de diseño en PHP: desde lo básico hasta técnicas avanzadas
Los patrones de diseño (design patterns) son soluciones probadas repetidamente para problemas típicos que surgen en el desarrollo de software. Para un desarrollador de PHP, conocer los patrones no es solo un punto en el currículum, sino una herramienta real para crear código flexible, mantenible y escalable. En este artículo, analizaremos tres grupos clave de patrones GoF (Gang of Four) con ejemplos concretos en PHP que podrá aplicar de inmediato en sus proyectos.
1. Patrones creacionales (Creational Patterns)
Estos patrones se encargan de la creación de objetos, ocultando la lógica de instanciación y haciendo que el sistema sea independiente de la forma de crear y componer objetos.
Singleton (Instancia única)
Garantiza que una clase tenga solo una instancia y proporciona un punto de acceso global a ella. Un ejemplo clásico es la conexión a la base de datos.
<?phpclass Database { private static ?Database $instance = null; private PDO $pdo;
private function __construct() { $this->pdo = new PDO('mysql:host=localhost;dbname=test', 'root', ''); }
public static function getInstance(): Database { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; }
public function query(string $sql): array { // Lógica de ejecución de la consulta return $this->pdo->query($sql)->fetchAll(); }
// Prohibir clonación y deserialización private function __clone() {} public function __wakeup() { throw new Exception("Cannot unserialize singleton"); }}
// Uso$db = Database::getInstance();$results = $db->query("SELECT * FROM users");?>Factory Method (Método fábrica)
Define una interfaz para crear un objeto, pero permite que las subclases alteren el tipo de objeto creado. Es ideal para crear familias de objetos relacionados.
<?phpinterface Logger { public function log(string $message): void;}
class FileLogger implements Logger { public function log(string $message): void { file_put_contents('app.log', $message . PHP_EOL, FILE_APPEND); }}
class DatabaseLogger implements Logger { public function log(string $message): void { // Guardar en la BD echo "Logged to DB: $message"; }}
abstract class LoggerFactory { abstract public function createLogger(): Logger;
public function logMessage(string $message): void { $logger = $this->createLogger(); $logger->log($message); }}
class FileLoggerFactory extends LoggerFactory { public function createLogger(): Logger { return new FileLogger(); }}
class DatabaseLoggerFactory extends LoggerFactory { public function createLogger(): Logger { return new DatabaseLogger(); }}
// Uso$factory = new FileLoggerFactory();$factory->logMessage("Este mensaje se escribirá en el archivo");?>2. Patrones estructurales (Structural Patterns)
Definen cómo las clases y objetos pueden combinarse en estructuras más grandes, manteniendo la flexibilidad y eficiencia.
Adapter (Adaptador)
Permite que objetos con interfaces incompatibles trabajen juntos. El adaptador actúa como un envoltorio que transforma las llamadas de una interfaz en otra.
<?php// Clase antigua con interfaz incómodaclass OldPaymentSystem { public function processPayment(float $amount, string $currency): string { return "Processing $amount $currency via legacy system"; }}
// Nueva interfaz que queremos usarinterface NewPaymentInterface { public function pay(float $amount): string;}
// Adaptadorclass PaymentAdapter implements NewPayme