toniGitH /
Patron-Builder
Explicación del patrón Builder y ejemplo de uso en PHP
Loading repository data…
toniGitH / repository
Explicación del patrón Decorator y ejemplo de uso en PHP
Repositorio creado para explicar el patrón Decorator y su implementación mediante un ejemplo práctico en PHP (Conversor de texto para web).
El patrón Decorator es un patrón estructural que permite añadir funcionalidades o responsabilidades a instancias (objetos) de una clase base, evitando cargarlas con lógicas opcionales que no forman parte de su naturaleza esencial.
Para lograrlo, el patrón propone la creación de una Interface Común que debe ser implementada tanto por esa clase base como por todas aquellas clases (llamadas decoradores) que sirvan para añadir esas funcionalidades o responsabilidades adicionales. Con la finalidad de reutilizar código y estandarizar las clases decoradores, éstas deberán extender de una clase abstracta que actúa de "modelo" para construir dichas clases.
En definitiva, el patrón Decorator permite que una aplicación construya procesos complejos y modulares "apilando" envoltorios sobre un objeto base, donde cada capa añade una capacidad única sin que el cliente (el componente que usa el objeto) necesite conocer la complejidad de la cadena de procesamiento.
Este patrón propone una arquitectura basada en los siguientes elementos clave:
1️⃣ Interface Común (InputFormatInterface)
Es el contrato que estandariza la forma de uso tanto del objeto inicial como de todos sus decoradores. Gracias a ella, la aplicación cliente depende de una abstracción y no de concreciones, desconociendo si está llamando al objeto base o a un decorador, lo que le permite funcionar sin necesidad de conocer la complejidad interna de la cadena.
2️⃣ Componente Concreto (AppInput)
Es la clase que representa el objeto original al que queremos añadir capacidades.
Dependiendo del contexto, este componente puede ser una clase con lógica compleja preexistente (como un sistema de envío de emails) o, como en nuestro ejemplo, una clase creada específicamente para convertir un dato primitivo (un string) en un objeto.
En este último caso, su función es vital para "objetivizar" el contenido, permitiendo que el patrón pueda empezar a trabajar sobre una instancia que rinda cuentas a la interfaz común.
3️⃣ Clase Abstracta Decoradora (AbstractDecorator)
Actúa como el modelo para todos los decoradores.
Su función es proporcionar una propiedad específica destinada a almacenar la referencia al objeto que se va a decorar (ya sea el núcleo original o un objeto que ya ha sido decorado previamente), facilitando así la delegación de llamadas hacia el interior de la cadena.
4️⃣ Decoradores Concretos
Son las clases (como MarkdownDecorator, DangerousHTMLTagsDecorator o PlainTextDecorator) que heredan del modelo abstracto para inyectar una lógica específica de filtrado, limpieza o transformación, antes o después de pasar la ejecución al siguiente elemento.
Su aplicación es ideal en situaciones donde la herencia tradicional se vuelve rígida o ineficiente.
Este patrón permite modificar el comportamiento en tiempo de ejecución. Mientras que la herencia es estática (se define al programar), el Decorator permite decidir qué funciones añadir y en qué orden mientras la aplicación ya está corriendo, adaptándose dinámicamente a las necesidades del momento.
Podemos identificar varios escenarios clave donde nos conviene usar este patrón.
Cuando ya disponemos de una clase que realiza una tarea concreta (ej. un Notificador de emails) y necesitamos añadirle capacidades adicionales (ej. enviar también por SMS, Slack o Facebook) sin modificar la clase original. Es la solución perfecta para evitar la explosión combinatoria de subclases.
Como hemos visto en nuestro proyecto, a veces queremos decorar algo que no es un objeto por naturaleza (como un string o un flujo de datos crudos). Usamos el patrón para crear una clase base portadora que "envuelve" ese dato, convirtiéndolo en un objeto que permite iniciar una cadena de procesamiento modular.
Cuando trabajas con librerías externas donde las clases están marcadas como final (no se pueden heredar). El Decorator es la única forma de extender su comportamiento envolviéndolas en un wrapper propio.
El uso del Decorator no solo resuelve problemas de extensibilidad, sino que mejora la calidad del código siguiendo las mejores prácticas de la Programación Orientada a Objetos (POO).
Permite desglosar una clase monolítica que hace muchas cosas en varias clases pequeñas y especializadas. Cada decorador hace una sola cosa (ej. uno filtra HTML, otro convierte Markdown).
Puedes introducir nuevos decoradores y funcionalidades sin tocar el código de las clases existentes ni el de los clientes que las usan. El sistema está "cerrado" a modificación pero "abierto" a extensión.
Favorece la composición sobre la herencia. La herencia es una relación de "ser" (es estática), mientras que la composición/decoración es una relación de "tener" y "envolver" (es dinámica). Esto hace que el sistema sea mucho más flexible y menos propenso a errores de jerarquías complejas.
Los decoradores son piezas independientes que pueden combinarse de infinitas maneras. Un decorador de "Seguridad" configurado una vez puede reutilizarse para decorar un sistema de archivos, una base de datos o un simple campo de texto.
Gracias al uso de una interfaz común, el cliente no necesita saber si está tratando con el objeto básico o con un objeto envuelto en diez capas de decoración. Esto reduce el acoplamiento y facilita el mantenimiento.
👉🏼 Comparativa Builder vs Decorator
Dado el detalle con el que se explica el ejemplo creado para visualizar el patrón Decorator, se ha decidido crear un documento específico para ello.
👉🏼 Explicación detallada del ejemplo
En este documento encontrarás una explicación más detallada de cómo encaja el patrón Decorator en el ejemplo creado:
👉🏼 Entendiendo el patrón Decorator
- `AppInput.php`: componente concreto que sirve como base de la decoración (convierte el texto en objeto "decorable").
- `InputFormatInterface.php`: interfaz común que garantiza que el cliente pueda tratar a todos por igual.
- `AbstractDecorator.php`: clase abstracta que estandariza la estructura de todos los decoradores.
- `MarkdownDecorator.php`: decorador concreto que transforma sintaxis Markdown en código HTML.
- `DangerousHTMLTagsDecorator.php`: decorador concreto que elimina etiquetas y atributos HTML peligrosos.
- `PlainTextDecorator.php`: decorador concreto que limpia cualquier rastro de HTML dejando solo texto plano.
WebsiteClient.php: aplicación cliente que depende de la abstracción para procesar el contenido.Ubicado en la raíz del proyecto: main.php.
Interfaz visual para comparar los resultados.
Ubicado en la raíz del proyecto: index.php y styles.css.
src/Para mantener el orden hemos movido todo el código fuente a la carpeta src/.
En lugar de tener una lista interminable de require_once "archivo.php" en nuestro main.php, utilizamos Composer para la carga automática de clases.
El archivo composer.json define el mapeo:
{
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
Esto significa que cualquier clase con el namespace que empiece por App\ será buscada automáticamente dentro de la carpeta src/. Por ejemplo, la clase AppInput estará en el namespace App\MyApp y se buscará en src/MyApp.
Gracias a esto, en nuestro main.php solo necesitamos una línea para cargar TODO el proyecto:
require "vendor/autoload.php";
Clona este repositorio o descarga los archivos.
Abre una terminal en la carpeta raíz del proyecto.
Ejecuta el siguiente comando para generar la carpeta vendor y el autoloader:
composer dump-autoload
💡 Nota: Como este proyecto no tiene dependencias de librerías externas (solo usamos Composer para el autoload), basta con
composer dump-autoload. Si hubiera librerías enrequire, usaríamoscomposer install.
Puedes ejecutar/visualizar la aplicación mediante el navegador (con XAMPP o con un servidor web local).
PHP trae un servidor web ligero que sirve para desarrollo. No necesitas instalar Apache ni XAMPP.
cd ~/Documentos/.../patrones/decorator
php -S localhost:8000
💡 No es obligatorio usar el puerto 8000, p
Selected from shared topics, language and repository description—not editorial ratings.
toniGitH /
Explicación del patrón Builder y ejemplo de uso en PHP
toniGitH /
Explicación del patrón Prototype y ejemplo de uso en PHP
toniGitH /
Explicación del patrón Singleton y ejemplo de uso en PHP
toniGitH /
Explicación del patrón Facade y ejemplo de uso en PHP
toniGitH /
Explicación del patrón Adapter y ejemplo de uso en PHP
toniGitH /
Explicación del patrón Abstract Factory y ejemplo de uso en PHP