Plus tôt dans cette série, nous avons exploré les modèles de conception de façade et d’adaptateur de cette série. En utilisant façade, nous pouvons simplifier les grands systèmes et, en mettant en œuvre un adaptateur, nous pouvons rester en sécurité lorsque nous travaillons avec des API et des classes externes. Nous allons maintenant couvrir le modèle de conception du décorateur, qui entre également dans la catégorie des modèles structurels..
Nous pouvons utiliser le modèle de décorateur lorsque nous voulons simplement donner une responsabilité supplémentaire à notre classe de base. Ce modèle de conception est une excellente alternative à une fonctionnalité de sous-classification pour étendre la fonctionnalité avec quelques avantages supplémentaires.
Si vous êtes confus et pensez que nous pouvons obtenir la même fonctionnalité avec une fonctionnalité de sous-classement, laissez-moi vous montrer quelques exemples de code qui élimineront votre confusion et vous feront aimer le motif de décorateur..
Je vais prendre l'exemple d'une classe chargée de générer du contenu pour un courrier électronique. Comme vous pouvez le constater, dans le bloc de code suivant, cette classe fonctionne très bien pour générer du contenu de courrier électronique sans aucune modification..
class eMailBody private $ header = 'Ceci est un en-tête de courrier électronique'; private $ footer = 'Ceci est un email Footer'; public $ body = "; public function loadBody () $ this-> body. =" Il s'agit du corps de l'e-mail principal..
";
Nous savons que Noël approche et disons que je souhaite saluer mon lecteur avec un message pour mon prochain courrier électronique. Donc, je dois ajouter un message dans le corps de mon email avec une image qui a l'air bien.
Pour cela, je peux directement éditer dans ma classe email, ce que je ne veux vraiment pas faire. Je peux donc mettre en œuvre l'héritage pour obtenir le même effet. Je crée une classe enfant distincte de la classe principale du corps de l'e-mail:
la classe christmasEmail étend eMailBody fonction publique loadBody () parent :: loadBody (); $ this-> body. = "Ajout de contenu pour Noël
"; $ christmasEmail = new christmasEmail (); $ christmasEmail-> loadBody (); echo $ christmasEmail-> body;
J'en ai donc terminé avec mon code et après quelques jours, je souhaite envoyer un courrier électronique avec les salutations du Nouvel An. Nous pouvons utiliser la même méthode que pour Noël.
La classe newYearEmail étend eMailBody fonction publique loadBody () parent :: loadBody (); $ this-> body. = "Contenu ajouté pour le Nouvel An
"; $ newYearEmail = new newYearEmail (); $ newYearEmail-> loadBody (); echo $ newYearEmail-> body;
Cela s'est bien passé sans plus de problèmes. Supposons maintenant que j'oublie de saluer mes visiteurs pour les deux occasions (Noël et Nouvel An) et que je veuille envoyer les deux salutations dans un seul courrier électronique, sans modifier aucun code dans la classe de base..
Votre esprit est immédiatement rempli de la question suivante: Est-ce que les sous-classes et l'héritage aideront ici? Je serais en faveur de cela, mais nous devrons utiliser du code supplémentaire / inutile pour y parvenir. Nous pouvons utiliser des traits qui nous permettent de mettre en œuvre quelque chose de similaire à l'héritage multiple.
Le problème que nous avons discuté dans la section précédente peut être résolu en implémentant le motif décoratif..
Selon Wikipedia:
Le modèle de décorateur (également appelé Wrapper, une autre dénomination partagée avec le modèle d'adaptateur) est un modèle de conception qui permet d'ajouter un comportement à un objet individuel, de manière statique ou dynamique, sans affecter le comportement des autres objets de la même classe..
Dans la section ci-dessus, nous avons vu que nous pouvons étendre les fonctionnalités / comportements en utilisant une sous-classe, mais lorsqu'il s'agit d'ajouter plusieurs fonctionnalités / comportements, cela devient long et complexe. Et c'est là que nous devrions utiliser le motif de décorateur.
interface eMailBody fonction publique loadBody ();
C'est une interface simple pour s'assurer que certaines classes doivent implémenter les méthodes requises.
class eMail implémente eMailBody public function loadBody () echo "Ceci est le corps de l'e-mail principal.
";
C'est la classe principale qui génère le corps par défaut d'un email, que j'utilise généralement pour envoyer des emails. Ce dont j'ai besoin, cependant, est de modifier le contenu du corps en fonction de l'occasion mais sans modifier la classe de messagerie principale..
La classe abstraite emailBodyDecorator implémente eMailBody protected $ emailBody; fonction publique __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody; fonction publique abstraite loadBody ();
Il s’agit de notre classe de décorateurs principale, qui contient la référence à notre classe de messagerie principale et modifie son comportement si nécessaire. Ici nous avons défini une méthode abstraite, loadBody
, quel sous-décorateur doit mettre en œuvre pour changer le comportement.
class christmasEmailBody étend emailBodyDecorator fonction publique loadBody () echo 'Ceci est un contenu supplémentaire pour Noël
'; $ this-> emailBody-> loadBody (); La classe newYearEmailBody étend emailBodyDecorator fonction publique loadBody () echo 'Ceci est un contenu supplémentaire pour le Nouvel An.
'; $ this-> emailBody-> loadBody ();
Ici, nous avons créé deux sous-classes du décorateur principal, qui changent le comportement de notre classe de messagerie principale..
Nous avons créé tous les éléments requis. Il suffit d’utiliser notre code et de profiter.
interface eMailBody fonction publique loadBody (); la classe eMail implémente eMailBody public function loadBody () echo "Ceci est le corps de l'e-mail principal.
"; la classe abstraite emailBodyDecorator implémente eMailBody protected $ emailBody; fonction publique __construct (eMailBody $ emailBody) $ this-> emailBody = $ emailBody; fonction publique abstraite loadBody (); classe christmasEmailBody étend emailBodyDecorator fonction publique loadBody ( ) echo 'Ceci est un contenu supplémentaire pour Noël
'; $ this-> emailBody-> loadBody (); La classe newYearEmailBody étend emailBodyDecorator fonction publique loadBody () echo 'Ceci est un contenu supplémentaire pour le Nouvel An.
'; $ this-> emailBody-> loadBody ();
Nous allons maintenant utiliser cette classe de décorateur de différentes manières, selon les besoins:
/ * * Email normal * / $ email = nouvel email (); $ email-> loadBody (); // Sortie Ceci est le corps de l'e-mail principal. / * * Email avec Xmas Greetings * / $ email = new eMail (); $ email = new christmasEmailBody ($ email); $ email-> loadBody (); // Sortie Ceci est un contenu supplémentaire pour Noël Ceci est le corps du message principal / * * Email avec les voeux du Nouvel An * / $ email = new eMail (); $ email = new newYearEmailBody ($ email); $ email-> loadBody (); // Sortie Ceci est un contenu supplémentaire pour le nouvel an. Ceci est le corps principal de l'e-mail. / * * Email avec les voeux de Noël et du nouvel an * / $ email = new eMail (); $ email = new christmasEmailBody ($ email); $ email = new newYearEmailBody ($ email); $ email-> loadBody (); // Sortie Ceci est un contenu supplémentaire pour le nouvel an. Ceci est un contenu supplémentaire pour Noël Ceci est le corps de l'e-mail principal.
Nous pouvons voir que maintenant nous avons modifié le corps d'un email sans modifier la classe email principale.
Chaque application dont nous disposons nécessite une sorte de modification et / ou d'amélioration à intervalles réguliers. Ainsi, dans un tel cas, nous pouvons implémenter le motif de conception du décorateur et cela améliorera la qualité du code et rendra notre code plus extensible.
Ce fut mon effort pour vous expliquer le modèle de décorateur, mais si vous avez des commentaires ou des questions supplémentaires, n'hésitez pas à les ajouter dans le fil ci-dessous.