Sobes.tech
Middle

Cos'è un decoratore (Decorator)?

sobes.tech AI

Risposta dell'AI

Il decoratore è un pattern di progettazione strutturale che consente di aggiungere dinamicamente nuove funzionalità a un oggetto, senza modificarne la struttura. Avvolge l'oggetto, fornendo la stessa interfaccia dell'oggetto avvolto, ma aggiungendo o modificando il suo comportamento.

Elementi principali:

  • Componente (Component): Interfaccia o classe astratta che definisce la funzionalità comune per gli oggetti avvolti e i decoratori.
  • Componente Concreto (Concrete Component): Implementazione del componente, oggetto di base a cui si aggiunge funzionalità.
  • Decoratore (Decorator): Classe astratta che implementa l'interfaccia del componente e contiene un riferimento a un oggetto componente.
  • Decoratore Concreto (Concrete Decorator): Implementazione del decoratore che aggiunge funzionalità specifica prima o dopo la chiamata del metodo dell'oggetto avvolto.

Esempio in Python:

# Componente
class Coffee:
    def get_cost(self):
        return 5 # Costo base del caffè
    
    def get_description(self):
        return "Caffè semplice"

# Componente Concreto
class SimpleCoffee(Coffee):
    pass

# Decoratore
class CoffeeDecorator(Coffee):
    def __init__(self, coffee):
        self._coffee = coffee

    def get_cost(self):
        return self._coffee.get_cost()

    def get_description(self):
        return self._coffee.get_description()

# Decoratore Concreto
class MilkDecorator(CoffeeDecorator):
    def get_cost(self):
        return self._coffee.get_cost() + 2 # Aggiunge il costo del latte

    def get_description(self):
        return self._coffee.get_description() + ", Latte"

# Uso
# simple_coffee = SimpleCoffee()
# print(f"Costo: {simple_coffee.get_cost()}, Descrizione: {simple_coffee.get_description()}")

# coffee_with_milk = MilkDecorator(simple_coffee)
# print(f"Costo: {coffee_with_milk.get_cost()}, Descrizione: {coffee_with_milk.get_description()}")

Vantaggi:

  • Flessibilità: La funzionalità può essere aggiunta durante l'esecuzione.
  • Evitare sottoclassi: Permette di evitare la creazione di molte sottoclassi per ogni combinazione di comportamenti.
  • Separazione delle responsabilità: Ogni aggiunta di comportamento viene gestita in una classe separata.

Svantaggi:

  • Potrebbe aumentare il numero di classi.
  • Il debug può diventare più complesso a causa della catena di avvolgimenti.