Patrones de diseño en PHP: qué son y para qué sirven
Los patrones de diseño (design patterns) son soluciones probadas para problemas típicos en la programación orientada a objetos. No son código listo para usar, sino plantillas que se pueden adaptar a una situación específica. En PHP, los patrones son especialmente útiles para crear aplicaciones web escalables y mantenibles.
En este artículo analizaremos tres patrones principales: Singleton, Factory y Observer. Para cada uno proporcionaremos ejemplos reales en PHP y explicaremos en qué situaciones conviene utilizarlos.
¿Por qué vale la pena estudiar los patrones en PHP?
- Simplificación del código — enfoque uniforme para resolver problemas.
- Reutilización — los patrones se adaptan fácilmente a diferentes proyectos.
- Facilidad de mantenimiento — el código se vuelve comprensible para otros desarrolladores.
- Capacidad de prueba — el uso de patrones facilita la escritura de unit-tests.
1. Patrón Singleton
Singleton garantiza que una clase tenga una única instancia y proporciona un punto de acceso global a ella. En PHP se utiliza a menudo para la conexión a bases de datos, registro de eventos (logging) o configuración.
Ejemplo: Clase para trabajar con la BD
<?phpclass Database { private static ?Database $instance = null; private PDO $connection;
private function __construct() { // Conexión a la BD (ejemplo con SQLite) $this->connection = new PDO('sqlite:example.db'); $this->connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); }
public static function getInstance(): Database { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; }
public function getConnection(): PDO { return $this->connection; }
// Prohibimos la clonación y deserialización private function __clone() {} public function __wakeup() { throw new \\Exception("Cannot unserialize singleton"); }}
// Uso$db = Database::getInstance();$pdo = $db->getConnection();?>¿Cuándo aplicar Singleton?
- Cuando se necesita exactamente una instancia de una clase (por ejemplo, conexión a la BD).
- Para acceso global a un recurso (logger, caché).
- En situaciones donde crear varias instancias provocaría conflictos.
Desventajas: viola el principio de responsabilidad única y dificulta las pruebas (crea un estado global).
2. Patrón Factory (Fábrica)
Factory Method (Método de fábrica) define una interfaz para crear un objeto, pero permite que las subclases modifiquen el tipo de objeto creado. Esto es útil cuando el tipo de objeto no se conoce de antemano o puede cambiar.
Ejemplo: Fábrica para crear notificaciones
<?php// Interfaz para todos los tipos de notificacionesinterface Notification { public function send(string $message): void;}
// Implementaciones concretasclass EmailNotification implements Notification { public function send(string $message): void { echo "Enviando email: {$message}"; }}
class SMSNotification implements Notification { public function send(string $message): void { echo "Enviando SMS: {$message}"; }}
// Fábricaclass NotificationFactory { public static function create(string $type): Notification { return match ($type) { 'email' => new EmailNotification(), 'sms' => new SMSNotification(), default => throw new \\InvalidArgumentException("Tipo desconocido: {$type}"), }; }}
// Uso$notification = NotificationFactory::create('email');$notifica