Modele de design modelul decorativ

Anterior, în această serie am explorat atât modelele de design ale fatadei, cât și ale adaptoarelor din această serie. Folosind fațada, putem simplifica sistemele mari și prin implementarea adaptorului putem rămâne în siguranță în timp ce lucrăm cu API și clase externe. Acum vom acoperi modelul de design al decoratorului, care, de asemenea, se încadrează în categoria modelelor structurale.

Putem folosi modelul decorativ când vrem doar să dăm o anumită responsabilitate suplimentară clasei de bază. Acest model de design este o alternativă excelentă la o caracteristică de subclasificare pentru extinderea funcționalității cu unele avantaje suplimentare.

Problema

Dacă sunteți confuz și credeți că putem obține aceleași funcționalități cu o caracteristică de subclassificare, atunci permiteți-mi să vă arăt câteva exemple de cod care vă vor elimina confuzia și vă vor face să vă place modelul de decorator.

Am de gând să iau un exemplu de clasă care este responsabilă pentru generarea de conținut pentru un e-mail. În următorul bloc de cod, după cum puteți vedea, această clasă funcționează foarte bine pentru generarea conținutului de e-mail fără nicio modificare.

class eMailBody privat $ header = 'Acesta este antetul emailului'; privat $ footer = 'Acesta este subsolul de e-mail'; public $ body = "; public function loadBody () $ this-> body. =" Acesta este principalul element de e-mail.
";

Știm că vine Crăciunul și să spunem că vreau să-i salut pe cititorul meu cu un mesaj pentru următorul meu e-mail de știri. Deci, trebuie să adaug un mesaj în corpul meu de e-mail cu o imagine care arată bine. 

Pentru aceasta pot edita direct în clasa mea de e-mail, ceea ce chiar nu vreau să fac. Deci, pot implementa moștenirea pentru a obține același efect. Creez o clasă de copii separată a clasei principale de e-mail:

clasa christmasEmail extinde eMailBody function public functionBody () parent = loadBody (); $ this-> body = "Adăugat Conținut pentru Xmas
"; $ christmasEmail = noul CrăciunEmail (); $ christmasEmail-> loadBody (); echo $ christmasEmail-> body;

Deci, am terminat cu codul meu și după câteva zile vreau să trimit un e-mail cu salutul de Anul Nou. Putem folosi aceeași metodă ca și pentru Crăciun.

class newYearEmail extinde eMailBody function public functionBody () parent :: loadBody (); $ this-> body = = "Conținutul adăugat pentru Anul Nou
"; $ newYearEmail = new newYearEmail (); $ newYearEmail-> loadBody (); echo $ newYearEmail-> body;

Acest lucru a mers fără probleme, fără alte probleme. Acum să spun că uit să-mi salut vizitatorii pentru ambele ocazii (Crăciun și Anul Nou) și vreau să trimit ambele felicitări într-un singur e-mail, fără a modifica nici un cod din clasa de bază. 

Mintea voastră se umple imediat cu următoarea întrebare: Vor ajuta subclasele și moștenirea aici? Aș fi în favoarea de a merge în acest fel, dar va trebui să folosim cod suplimentar / inutil pentru a realiza acest lucru. Putem folosi trăsături care ne permit să implementăm ceva similar cu moștenirea multiplă.

Soluția

Problema pe care am discutat-o ​​în secțiunea anterioară poate fi rezolvată prin implementarea modelului de decorator. 

Potrivit Wikipedia:

Modelul de decorator (cunoscut și ca Wrapper, o denumire alternativă împărtășită cu modelul Adaptor) este un model de design care permite adăugarea unui comportament unui obiect individual, fie static, fie dinamic, fără a afecta comportamentul altor obiecte din aceeași clasă.

În secțiunea de mai sus am văzut că putem extinde caracteristici / comportament folosind o subclasă, dar când vine vorba de adăugarea mai multor caracteristici / comportamente, devine mult timp și complex. Și acolo ar trebui să folosim modelul de decorator.

Interfață

interfața eMailBody load public functionBody (); 

Aceasta este o interfață simplă pentru a vă asigura că o anumită clasă trebuie să implementeze metodele necesare. 

Clasa principală de e-mail

eMail-ul de clasă implementează eMailBody load public functionBody () echo "Acesta este principalul element de e-mail.
";

Aceasta este clasa principală care generează corpul implicit al unui e-mail, pe care îl folosesc în general pentru a trimite e-mailuri. Ceea ce am nevoie, totuși, este de a modifica conținutul corpului bazat pe o anumită ocazie, dar fără a modifica clasa principală de e-mail.

Decoratorul principal

clasa abstracte emailBodyDecorator pune în aplicare eMailBody protected $ emailBody; funcția publică __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody;  funcția publică abstractăBody ();  

Aceasta este clasa principală a decoratorilor, care deține referința la clasa principală de e-mail și își schimbă comportamentul după cum este necesar. Aici am definit o metodă abstractă, loadBody, care sub-decorator trebuie să implementeze pentru a schimba comportamentul.

Sub Decorator

class christmasEmailBody extinde emailBodyDecorator function public loadBody () echo 'Acesta este un conținut suplimentar pentru Crăciun
„; $ This-> emailBody-> loadBody (); class newYearEmailBody extinde emailBodyDecorator public function loadBody () echo 'Acesta este conținut suplimentar pentru Anul Nou.
„; $ This-> emailBody-> loadBody ();

Aici am creat două sub-clase ale decoratorului principal, care efectuează, de fapt, o schimbare de comportament pentru clasa principală de e-mail.

Împachetarea tuturor împreună

Am creat toate elementele necesare. Tot ce trebuie să facem este să folosim codul nostru și să ne bucurăm.

interfața eMailBody load public functionBody ();  eMail de clasă implementează eMailBody funcția publică funcțiaBody () echo "Acesta este principalul element e-mail.
" abstract class emailBodyDecorator implementează eMailBody protejat $ emailBody; funcția publică __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody; funcția public abstract loadBody (); class christmasEmailBody extinde emailBodyDecorator public function loadBody ) echo 'Acesta este un conținut suplimentar pentru Crăciun
„; $ This-> emailBody-> loadBody (); class newYearEmailBody extinde emailBodyDecorator public function loadBody () echo 'Acesta este conținut suplimentar pentru Anul Nou.
„; $ This-> emailBody-> loadBody ();

Acum vom folosi această clasă de decoratori în diferite moduri, după cum este necesar:

/ * * Email normal * / $ email = nou eMail (); $ Email-> loadBody (); // Output Acesta este principalul element de e-mail. / * * Email cu salutări Xmas * / $ email = nou eMail (); $ email = noul CrăciunEmailBody ($ email); $ Email-> loadBody (); // Output Acesta este un conținut suplimentar pentru Crăciun Acesta este principalul corp de e-mail. / * * Email cu salutări de Anul Nou * / $ email = nou eMail (); $ email = noul nouYearEmailBody ($ email); $ Email-> loadBody (); // Output Acesta este un conținut suplimentar pentru Anul Nou. Acesta este principalul element de e-mail. / * * E-mail cu salutări de Crăciun și de Anul Nou * / $ email = nou eMail (); $ email = noul CrăciunEmailBody ($ email); $ email = noul nouYearEmailBody ($ email); $ Email-> loadBody (); // Output Acesta este un conținut suplimentar pentru Anul Nou. Acesta este un conținut suplimentar pentru Crăciun Acesta este principalul element de e-mail.

Putem vedea că acum am modificat corpul unui e-mail fără a modifica clasa principală de e-mail.

Concluzie

Fiecare aplicație pe care o avem are nevoie de un fel de modificare și / sau îmbunătățiri la intervale uniforme. Deci, într-un astfel de caz, putem implementa modelul de design al decoratorului și, în cele din urmă, vom îmbunătăți calitatea codului și vom face codul mai extensibil.

Acesta a fost efortul meu de a vă explica despre modelul de decorator, dar dacă aveți comentarii sau întrebări suplimentare, vă rugăm să nu ezitați să le adăugați în feed-ul de mai jos.

Cod