Patrones de diseño en PHP: nivel avanzado
\n\nLos patrones de diseño (design patterns) son soluciones probadas para problemas típicos que surgen durante el desarrollo de software. En el nivel inicial, los desarrolladores estudian Singleton, Factory o Adapter. Sin embargo, en sistemas complejos, de alta carga o flexibles en PHP, se requieren plantillas más potentes y abstractas. En este artículo, analizaremos cuatro patrones avanzados con ejemplos reales de código en PHP: Estrategia, Método Fábrica, Observador y Estado.
\n\n1. Patrón "Estrategia" (Strategy)
\n\nPropósito: Define una familia de algoritmos, encapsula cada uno de ellos y los hace intercambiables. Permite cambiar el comportamiento de un objeto en tiempo de ejecución sin modificar su código.
\n\nEjemplo: Sistema de procesamiento de pagos. Tenemos varios métodos de pago: tarjeta de crédito, PayPal, criptomoneda. Cada método tiene su propia lógica de validación y procesamiento.
\n\n<?php\n\n// Interfaz de estrategia\ninterface PaymentStrategy\n{\n public function pay(float $amount): void;\n public function validate(): bool;\n}\n\n// Estrategias concretas\nclass CreditCardPayment implements PaymentStrategy\n{\n private string $cardNumber;\n private string $cvv;\n\n public function __construct(string $cardNumber, string $cvv)\n {\n $this->cardNumber = $cardNumber;\n $this->cvv = $cvv;\n }\n\n public function validate(): bool\n {\n // Verificación simple de la longitud del número de tarjeta\n return strlen($this->cardNumber) === 16 && strlen($this->cvv) === 3;\n }\n\n public function pay(float $amount): void\n {\n if (!$this->validate()) {\n throw new \\InvalidArgumentException("Datos de tarjeta inválidos");\n }\n echo "Pagado {$amount} con tarjeta de crédito {$this->cardNumber}.<br>";\n }\n}\n\nclass PayPalPayment implements PaymentStrategy\n{\n private string $email;\n\n public function __construct(string $email)\n {\n $this->email = $email;\n }\n\n public function validate(): bool\n {\n return filter_var($this->email, FILTER_VALIDATE_EMAIL) !== false;\n }\n\n public function pay(float $amount): void\n {\n if (!$this->validate()) {\n throw new \\InvalidArgumentException("Email de PayPal inválido");\n }\n echo "Pagado {$amount} a través de PayPal ({$this->email}).<br>";\n }\n}\n\n// Contexto (cliente)\nclass OrderProcessor\n{\n private PaymentStrategy $strategy;\n\n public function setPaymentStrategy(PaymentStrategy $strategy): void\n {\n $this->strategy = $strategy;\n }\n\n public function processOrder(float $total): void\n {\n if (!isset($this->strategy)) {\n throw new \\RuntimeException("Método de pago no seleccionado");\n }\n $this->strategy->pay($total);\n }\n}\n\n// Uso\n$order = new OrderProcessor();\n$order->setPaymentStrategy(new CreditCardPayment('1234567812345678', '123'));\n$order->processOrder(150.00);\n// Salida: Pagado 150 con tarjeta de crédito 1234567812345678.\n\n?>\n\nVentajas: Fácil añadir nuevos algoritmos (nuevos métodos de pago) sin modificar el código existente. El código se vuelve flexible y testeable.
\n\n2. Patrón "Método Fábrica" (Factory Method)
\n\nPropósito: Define una interfaz para crear un objeto, pero permite que las subclases alteren el tipo de objeto creado. Es el patrón base para todos los patrones de creación.
\n\nEjemplo: Generación de diferentes tipos de informes (PDF, HTML, JSON) según la solicitud del usuario.
\n\n<?php\n\n// Producto abstracto\ninterface Report\n{\n public function generate(): string;\n}\n\n// Productos concretos\nclass PdfReport implements Report\n