Middle
¿Qué es un decorador?
sobes.tech AI
Respuesta de la IA
Un decorador es un patrón de diseño estructural que permite agregar dinámicamente un comportamiento nuevo a los objetos, envolviéndolos en objetos decoradores especiales.
Principios básicos:
- Composición en lugar de herencia. El decorador amplía la funcionalidad del objeto sin cambiar su clase ni usar herencia.
- Flexibilidad. Permite agregar o eliminar responsabilidades del objeto en tiempo de ejecución.
- Compatibilidad. Los decoradores y los objetos envueltos tienen una interfaz común, lo que permite usarlos de manera intercambiable.
Estructura:
- Componente (Component): Interfaz para objetos a los que se pueden agregar responsabilidades dinámicamente.
- Componente concreto (ConcreteComponent): Implementación del Componente.
- Decorador (Decorator): Clase o interfaz abstracta que extiende el Componente y contiene una referencia a un objeto Componente.
- Decoradores concretos (Concrete Decorators): Implementaciones del Decorador que añaden comportamientos específicos.
Ejemplo (Python):
// Interfaz del componente
class Coffee:
def get_cost(self):
pass
def get_description(self):
pass
// Componente concreto
class SimpleCoffee(Coffee):
def get_cost(self):
return 1.0
def get_description(self):
return "Café simple"
// Decorador base
class CoffeeDecorator(Coffee):
def __init__(self, decorated_coffee):
self._decorated_coffee = decorated_coffee
def get_cost(self):
return self._decorated_coffee.get_cost()
def get_description(self):
return self._decorated_coffee.get_description()
// Decorador concreto (Leche)
class MilkDecorator(CoffeeDecorator):
def get_cost(self):
return self._decorated_coffee.get_cost() + 0.5
def get_description(self):
return self._decorated_coffee.get_description() + ", Leche"
// Uso
coffee = SimpleCoffee()
print(f"{coffee.get_description()}: ${coffee.get_cost()}") # Café simple: $1.0
coffee_with_milk = MilkDecorator(coffee)
print(f"{coffee_with_milk.get_description()}: ${coffee_with_milk.get_cost()}") # Café simple, Leche: $1.5
Ventajas:
- Forma más flexible de ampliar la funcionalidad de los objetos que la herencia.
- Evita la proliferación de subclases relacionadas con la herencia.
- Permite agregar múltiples "capas" de comportamiento a un solo objeto.
Desventajas:
- Puede complicar el código debido a la gran cantidad de objetos pequeños.
- El orden de envolvimiento puede ser importante.
Aplicación en QA / Automatización:
- Añadir registro a métodos existentes sin modificar su código fuente.
- Implementar manejo de excepciones para llamadas específicas.
- Añadir temporización o métricas de rendimiento.
- Uso en bibliotecas de automatización de pruebas (por ejemplo, en el patrón Page Object para agregar verificaciones o registros durante la interacción con elementos).