EMZETT.
Login

Decorator-Muster (Dekorierer)

Kurz: Das Decorator-Muster erweitert ein Objekt um zusätzliche Funktionen, indem man es in ein Hüllobjekt mit derselben Schnittstelle verpackt – ohne die Klasse zu ändern oder davon zu erben.

Genauer: Mehrere Dekoratoren lassen sich ineinander stecken, zum Beispiel Logging, Caching, Berechtigungsprüfung und Zeitmessung um dieselbe Funktion. Python hat dafür eine eigene Syntax (@dekorator), JavaScript/TypeScript kennt Decorators für Klassen, Java nutzt es bei Streams (new BufferedReader(new FileReader(...))).

Im Detail

import time
from functools import wraps
 
def zeitmessung(f):
    @wraps(f)
    def huelle(*args, **kwargs):
        start = time.perf_counter()
        ergebnis = f(*args, **kwargs)
        print(f"{f.__name__} dauerte {time.perf_counter() - start:.4f} s")
        return ergebnis
    return huelle
 
def nur_angemeldet(f):
    @wraps(f)
    def huelle(benutzer, *args, **kwargs):
        if not benutzer:
            raise PermissionError("Bitte anmelden")
        return f(benutzer, *args, **kwargs)
    return huelle
 
@zeitmessung
@nur_angemeldet
def bericht(benutzer):
    return f"Bericht für {benutzer}"
 
print(bericht("Mia"))

Objektorientierte Variante

interface Kaffee { double preis(); String text(); }
class Espresso implements Kaffee { public double preis() { return 2.0; } public String text() { return "Espresso"; } }
 
class MitMilch implements Kaffee {
    private final Kaffee innen;
    MitMilch(Kaffee k) { innen = k; }
    public double preis() { return innen.preis() + 0.5; }
    public String text() { return innen.text() + " mit Milch"; }
}
// new MitMilch(new MitMilch(new Espresso())) -> "Espresso mit Milch mit Milch", 3.0

Abgrenzung

Vererbung legt Erweiterungen beim Schreiben fest (Vererbung); Dekoratoren kombinieren sie zur Laufzeit beliebig. Das Muster hängt eng mit Closures und Funktionen höherer Ordnung zusammen, die Funktionen als Werte übernehmen und zurückgeben.

Siehe auch: Higher-Order-Funktion, Annotationen, Strategy-Muster, Vererbung