Sobes.tech
Middle

Was ist ein Dekorator?

sobes.tech KI

Antwort von AI

Ein Decorator ist ein strukturelles Entwurfsmuster, das es ermöglicht, Objekten dynamisch neues Verhalten hinzuzufügen, indem sie in spezielle Decorator-Objekte eingehüllt werden.

Grundprinzipien:

  • Komposition statt Vererbung. Der Decorator erweitert die Funktionalität des Objekts, ohne seine Klasse zu ändern oder Vererbung zu verwenden.
  • Flexibilität. Erlaubt das Hinzufügen oder Entfernen von Verantwortlichkeiten des Objekts zur Laufzeit.
  • Kompatibilität. Decorators und die eingehüllten Objekte haben eine gemeinsame Schnittstelle, was ihre interchangeable Nutzung ermöglicht.

Struktur:

  • Komponente (Component): Schnittstelle für Objekte, denen dynamisch Verantwortlichkeiten hinzugefügt werden können.
  • Konkrete Komponente (ConcreteComponent): Implementierung der Komponente.
  • Decorator (Decorator): Abstrakte Klasse oder Schnittstelle, die die Komponente erweitert und eine Referenz auf ein Komponentenobjekt enthält.
  • Konkrete Decorators (Concrete Decorators): Implementierungen des Decorators, die spezifisches Verhalten hinzufügen.

Beispiel (Python):

// Schnittstelle der Komponente
class Coffee:
    def get_cost(self):
        pass

    def get_description(self):
        pass

// Konkrete Komponente
class SimpleCoffee(Coffee):
    def get_cost(self):
        return 1.0

    def get_description(self):
        return "Einfacher Kaffee"

// Basischer Decorator
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()

// Konkreter Decorator (Milch)
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() + ", Milch"

// Verwendung
coffee = SimpleCoffee()
print(f"{coffee.get_description()}: ${coffee.get_cost()}") # Einfacher Kaffee: $1.0

coffee_with_milk = MilkDecorator(coffee)
print(f"{coffee_with_milk.get_description()}: ${coffee_with_milk.get_cost()}") # Einfacher Kaffee, Milch: $1.5

Vorteile:

  • Flexiblere Erweiterung der Funktionalität im Vergleich zur Vererbung.
  • Vermeidung der Zunahme von Subklassen im Zusammenhang mit Vererbung.
  • Ermöglicht das Hinzufügen mehrerer "Schichten" von Verhalten zu einem einzelnen Objekt.

Nachteile:

  • Kann den Code durch die Vielzahl kleiner Objekte verkomplizieren.
  • Die Reihenfolge des Einhüllens kann wichtig sein.

Anwendung in QA / Automatisierung:

  • Hinzufügen von Logging zu bestehenden Methoden ohne deren Quellcode zu ändern.
  • Implementierung von Ausnahmebehandlungen für bestimmte Aufrufe.
  • Hinzufügen von Timing- oder Leistungsmetriken.
  • Verwendung in Testautomatisierungsbibliotheken (z.B. im Page Object Pattern, um Überprüfungen oder Logging bei der Interaktion mit Elementen hinzuzufügen).