Ce este
Modelul Decorator adaugă comportament unui obiect împachetându-l într-un alt obiect cu aceeași interfață. Fiecare înveliș își face partea sa suplimentară și transmite apelul mai departe către ceea ce împachetează.
Pentru că învelișul și obiectul împachetat au aceeași interfață, învelișurile se pot stivui în orice combinație — ca straturile de haine.
Exemplu: împachetarea unui notificator
Notificatorul simplu trimite un email. Un înveliș adaugă jurnalizare înainte de trimitere; altul adaugă un SMS după. Apelantul vede în continuare un simplu Notifier.
Straturi în jurul unui nucleu
WithLog{WithSMS{EmailNotifier{}}} se citește dinspre interior spre exterior: emailul în nucleu, SMS-ul în jurul lui, jurnalizarea cel mai în exterior. Orice strat poate fi adăugat, eliminat sau reordonat fără a atinge celelalte straturi.
Ieșire: program Go și rezultatul capturat
package main
import "fmt"
type Notifier interface {
Send(msg string)
}
type EmailNotifier struct{}
func (EmailNotifier) Send(msg string) {
fmt.Println("email:", msg)
}
// Fiecare decorator împachetează un Notifier și adaugă un singur strat.
type WithLog struct {
wrapped Notifier
}
func (w WithLog) Send(msg string) {
fmt.Println("log: se trimite o notificare")
w.wrapped.Send(msg)
}
type WithSMS struct {
wrapped Notifier
}
func (w WithSMS) Send(msg string) {
w.wrapped.Send(msg)
fmt.Println("sms:", msg)
}
func main() {
n := WithLog{WithSMS{EmailNotifier{}}}
n.Send("serverul este oprit")
}
Când să îl folosești
Folosește-l pentru a adăuga comportamente opționale și combinabile — jurnalizare, memorare în cache, reîncercări, măsurători — în jurul unui nucleu pe care nu vrei să îl modifici. Middleware-ul din serverele web este exact acest model.
Renunță la el când comportamentul nu este opțional și nu este combinabil — atunci el aparține chiar tipului respectiv, unde este mai ușor de găsit.
Avantaje și dezavantaje
Avantaje: comportamentul se adaugă fără a atinge tipul 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 de a face ceva; liniile de construcție devin lungi.