Sobes.tech
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).