Middle
Cos'è un decoratore?
sobes.tech AI
Risposta dell'AI
Un decoratore è un pattern di progettazione strutturale che consente di aggiungere dinamicamente un nuovo comportamento agli oggetti, avvolgendoli in oggetti decoratori speciali.
Principi fondamentali:
- Composizione invece di ereditarietà. Il decoratore espande la funzionalità dell'oggetto senza modificarne la classe e senza usare ereditarietà.
- Flessibilità. Permette di aggiungere o rimuovere responsabilità dell'oggetto durante l'esecuzione.
- Compatibilità. Decoratori e oggetti avvolti condividono un'interfaccia comune, che permette di usarli in modo intercambiabile.
Struttura:
- Componente (Component): Interfaccia per gli oggetti a cui si possono aggiungere responsabilità dinamicamente.
- Componente concreto (ConcreteComponent): Implementazione del componente.
- Decoratore (Decorator): Classe o interfaccia astratta che estende il componente e contiene un riferimento a un oggetto componente.
- Decoratori concreti (Concrete Decorators): Implementazioni del decoratore che aggiungono comportamenti specifici.
Esempio (Python):
// Interfaccia 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 "Caffè semplice"
// Decoratore 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()
// Decoratore concreto (Latte)
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() + ", Latte"
// Uso
coffee = SimpleCoffee()
print(f"{coffee.get_description()}: ${coffee.get_cost()}") # Caffè semplice: $1.0
coffee_with_milk = MilkDecorator(coffee)
print(f"{coffee_with_milk.get_description()}: ${coffee_with_milk.get_cost()}") # Caffè semplice, Latte: $1.5
Vantaggi:
- Modo più flessibile di espandere la funzionalità degli oggetti rispetto all'ereditarietà.
- Evita la proliferazione di sottoclassi legate all'ereditarietà.
- Permette di aggiungere più "strati" di comportamento a un singolo oggetto.
Svantaggi:
- Può complicare il codice a causa del gran numero di piccoli oggetti.
- L'ordine di avvolgimento può essere importante.
Applicazioni in QA / Automazione:
- Aggiunta di logging ai metodi esistenti senza modificarne il codice sorgente.
- Implementazione di gestione delle eccezioni per chiamate specifiche.
- Aggiunta di temporizzazione o metriche di prestazioni.
- Utilizzo in librerie di automazione dei test (ad esempio, nel pattern Page Object per aggiungere controlli o logging durante l'interazione con gli elementi).