Eerder in deze serie hebben we zowel de gevel- als adapterontwerppatronen in deze serie onderzocht. Met behulp van gevel kunnen we grote systemen vereenvoudigen en door een adapter te implementeren, kunnen we veilig blijven werken met externe API en klassen. Nu gaan we het patroon van de decorateur ontwerpen, dat ook onder de categorie structurele patronen valt.
We kunnen het patroon van de decorateur gebruiken als we gewoon wat extra verantwoordelijkheid willen toevoegen aan onze basisklasse. Dit ontwerppatroon is een geweldig alternatief voor een subklasse-functie om de functionaliteit uit te breiden met enkele extra voordelen.
Als je in de war bent en denkt dat we dezelfde functionaliteit ook kunnen bereiken met een subklasse-functie, laat me je dan enkele codevoorbeelden zien die je verwarring wegnemen en je laten genieten van het decorateurpatroon.
Ik ga een voorbeeld nemen van een klas die verantwoordelijk is voor het genereren van inhoud voor een e-mail. In het volgende codeblok, zoals je kunt zien, functioneert deze klasse erg goed voor het genereren van e-mailinhoud zonder enige wijziging.
class eMailBody private $ header = 'Dit is e-mail header'; private $ footer = 'Dit is e-mail Footer'; public $ body = "; public function loadBody () $ this-> body. =" Dit is het hoofdgedeelte van de e-mail.
";
We weten dat Kerstmis komt, en laten we zeggen dat ik mijn lezer wil groeten met een bericht voor mijn volgende nieuwsbrief-e-mail. Dus ik moet een bericht in mijn e-mailbericht toevoegen met een afbeelding die er goed uitziet.
Hiervoor kan ik rechtstreeks in mijn e-mail les bewerken, wat ik echt niet wil doen. Dus ik kan overerving implementeren om hetzelfde effect te bereiken. Ik maak een aparte onderliggende klasse van de hoofd-e-maillichaamklasse:
class christmasEmail breidt eMailBody uit public function loadBody () parent :: loadBody (); $ this-> body. = "Toegevoegde content voor kerstmis
"; $ christmasEmail = new christmasEmail (); $ christmasEmail-> loadBody (); echo $ christmasEmail-> body;
Dus ik ben klaar met mijn code, en na een paar dagen wil ik een e-mail sturen met nieuwjaarswensen. We kunnen dezelfde methode gebruiken als voor Kerstmis.
class newYearEmail breidt eMailBody uit public function loadBody () parent :: loadBody (); $ this-> body. = "Toegevoegde content voor nieuwjaar
"; $ newYearEmail = new newYearEmail (); $ newYearEmail-> loadBody (); echo $ newYearEmail-> body;
Dit verliep probleemloos zonder problemen. Nu laten we zeggen dat ik vergeet mijn bezoekers te begroeten voor beide gelegenheden (Kerstmis en Nieuwjaar) en ik wil beide begroetingen in één e-mail verzenden, zonder de code in de basisklasse te wijzigen.
Je geest wordt meteen gevuld met de volgende vraag: zullen subklassen en overerving hier helpen? Ik zou er voor zijn om die kant op te gaan, maar we zullen extra / onnodige code moeten gebruiken om dit te bereiken. We kunnen eigenschappen gebruiken die ons in staat stellen iets te implementeren dat lijkt op meerdere overerving.
Het probleem dat we in de vorige paragraaf hebben besproken, kan worden opgelost door het patroon van de decorateur te implementeren.
Volgens Wikipedia:
Het decorateurpatroon (ook bekend als Wrapper, een alternatieve naamgeving die wordt gedeeld met het adapterpatroon) is een ontwerppatroon waarmee gedrag aan een afzonderlijk object kan worden toegevoegd, hetzij statisch of dynamisch, zonder het gedrag van andere objecten uit dezelfde klasse te beïnvloeden.
In de bovenstaande sectie hebben we gezien dat we functies / gedrag kunnen uitbreiden met één subklasse, maar als het gaat om het toevoegen van meerdere functies / gedragingen, wordt het lang en complex. En dat is waar we het decoratorpatroon zouden moeten gebruiken.
interface eMailBody openbare functie loadBody ();
Dit is een eenvoudige interface om ervoor te zorgen dat sommige klassen de vereiste methoden moeten implementeren.
class eMail implementeert eMailBody public function loadBody () echo "Dit is het hoofdgedeelte van e-mail.
";
Dit is de hoofdklasse die de standaardtekst van een e-mail genereert, die ik meestal gebruik om e-mails te verzenden. Wat ik echter nodig heb, is het aanpassen van de inhoud van het lichaam op basis van een bepaalde gelegenheid, maar zonder de hoofd-e-mailklasse te wijzigen.
abstracte klasse emailBodyDecorator implementeert eMailBody protected $ emailBody; openbare functie __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody; abstracte openbare functie loadBody ();
Dit is onze belangrijkste decoratorklasse, die de verwijzing naar onze hoofd-e-mailklasse bevat en zijn gedrag naar behoefte aanpast. Hier hebben we een abstracte methode gedefinieerd, loadBody
, welke sub-decorateur moet implementeren om gedrag te veranderen.
class christmasEmailBody verlengt emailBodyDecorator openbare functie loadBody () echo 'Dit is Extra Content voor Kerstmis
'; $ This-> emailBody-> loadBody (); class newYearEmailBody verlengt emailBodyDecorator public function loadBody () echo 'Dit is Extra Content voor Nieuwjaar.
'; $ This-> emailBody-> loadBody ();
Hier hebben we twee subklassen van de hoofddecorator gemaakt, die feitelijk een gedragsverandering voor onze hoofd-e-mailklasse uitvoert.
We hebben alle benodigde elementen gemaakt. Het enige wat we moeten doen is onze code gebruiken en genieten.
interface eMailBody openbare functie loadBody (); class eMail implementeert eMailBody public function loadBody () echo "Dit is het hoofdgedeelte van de e-mail.
"; abstracte klasse emailBodyDecorator implementeert eMailBody protected $ emailBody; public function __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody; abstracte openbare functie loadBody (); class christmasEmailBody breidt emailBodyDecorator uit openbare functie loadBody ( ) echo 'Dit is extra inhoud voor Kerstmis
'; $ This-> emailBody-> loadBody (); class newYearEmailBody verlengt emailBodyDecorator public function loadBody () echo 'Dit is Extra Content voor Nieuwjaar.
'; $ This-> emailBody-> loadBody ();
Nu zullen we deze decoratorklasse op verschillende manieren gebruiken als dat nodig is:
/ * * Normale e-mail * / $ email = nieuwe e-mail (); $ Email-> loadBody (); // Uitvoer Dit is het hoofdgedeelte van e-mail. / * * Email with Xmas Greetings * / $ email = new eMail (); $ email = new christmasEmailBody ($ email); $ Email-> loadBody (); // Uitgang Dit is extra inhoud voor kerst Dit is het hoofdgedeelte van e-mail. / * * E-mail met nieuwjaarsgroeten * / $ email = nieuwe eMail (); $ email = new newYearEmailBody ($ email); $ Email-> loadBody (); // Uitgang Dit is extra content voor nieuwjaar. Dit is het hoofdgedeelte van Email. / * * Email met kerst- en nieuwjaarsgroeten * / $ email = nieuwe eMail (); $ email = new christmasEmailBody ($ email); $ email = new newYearEmailBody ($ email); $ Email-> loadBody (); // Uitgang Dit is extra content voor nieuwjaar. Dit is Extra Content voor Kerstmis Dit is het hoofdgedeelte van Email.
We kunnen zien dat we nu de inhoud van een e-mail hebben gewijzigd zonder de hoofd-e-mailklasse te wijzigen.
Elke applicatie die we hebben heeft een soort van aanpassing en / of verbetering nodig met uniforme intervallen. In een dergelijk geval kunnen we het ontwerppatroon van de decorateur implementeren en dit zal uiteindelijk de kwaliteit van de code verbeteren en onze code meer uitbreidbaar maken.
Dit was mijn poging om u uit te leggen over het decorateurpatroon, maar als u aanvullende opmerkingen of vragen heeft, aarzel dan niet om deze in de onderstaande feed toe te voegen.