Ce este
Șablonul Decorator adaugă comportament unui obiect prin învelirea lui într-un alt obiect cu aceeași interfață. Fiecare înveliș își face partea suplimentară și transmite apelul mai departe obiectului pe care îl învelește.
Deoarece învelișul și obiectul învelit au aceeași interfață, învelișurile se pot suprapune în orice combinație — ca straturile de haine.
Sintaxa @decorator din Python este aceeași idee aplicată funcțiilor — un înveliș în jurul unui apel. Această pagină arată forma cu obiecte, în care straturile sunt alese și suprapuse în timpul rulării.
Exemplu: învelirea unui notificator
Notificatorul simplu trimite un email. Un înveliș adaugă jurnalizare înainte de trimitere; altul adaugă un SMS după ea. Codul apelant vede în continuare un simplu Notifier.
Straturi în jurul unui nucleu
WithLog(WithSMS(EmailNotifier())) se citește din interior spre exterior: emailul în nucleu, SMS-ul în jurul lui, jurnalizarea la exterior. Orice strat poate fi adăugat, eliminat sau reordonat fără a le atinge pe celelalte.
Ieșire: program Python complet
from typing import Protocol
class Notifier(Protocol):
def send(self, msg: str) -> None: ...
class EmailNotifier:
def send(self, msg: str) -> None:
print("email:", msg)
# Fiecare decorator învelește un Notifier și adaugă un strat.
class WithLog:
def __init__(self, wrapped: Notifier):
self.wrapped = wrapped
def send(self, msg: str) -> None:
print("jurnal: se trimite o notificare")
self.wrapped.send(msg)
class WithSMS:
def __init__(self, wrapped: Notifier):
self.wrapped = wrapped
def send(self, msg: str) -> None:
self.wrapped.send(msg)
print("sms:", msg)
n = WithLog(WithSMS(EmailNotifier()))
n.send("serverul nu funcționează")
Când să îl folosești
Folosește-l pentru a adăuga comportament opțional și combinabil — jurnalizare, cache, reîncercări, metrici — în jurul unui nucleu pe care nu vrei să îl modifici. Middleware-ul din serverele web este exact acest șablon.
Renunță la el când comportamentul nu este opțional și nu este combinabil — atunci locul lui este chiar în interiorul clasei, unde este mai ușor de găsit.
Avantaje și dezavantaje
Avantaje: comportament adăugat fără a atinge clasa de bază; straturile se combină liber; fiecare strat este mic și poate fi testat separat.
Dezavantaje: o stivă adâncă de învelișuri este greu de depanat — apelul parcurge un drum lung înainte să facă ceva; liniile de construire devin lungi.