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 Facade, nous pouvons simplifier les grands systèmes et en implémentant des adaptateurs, nous pouvons rester en sécurité lors de l'utilisation d'API et de classes externes. Nous allons maintenant présenter le modèle de conception du décorateur, qui entre également dans la catégorie des modèles structurels.
Lorsque nous voulons simplement donner des responsabilités supplémentaires à la classe de base, nous pouvons utiliser le modèle décorateur. Ce modèle de conception est une excellente alternative aux fonctionnalités de sous-classement, étendant les fonctionnalités et offrant des avantages supplémentaires.
Si vous êtes confus et pensez que nous pouvons également obtenir la même fonctionnalité en sous-classant les fonctionnalités, laissez-moi vous montrer quelques exemples de code qui dissiperont votre confusion et vous feront aimer le modèle de décorateur.
Je vais donner un exemple de classe chargée de générer du contenu d'e-mail. Dans le bloc de code suivant, comme vous pouvez le voir, cette classe génère très bien le contenu de l'e-mail sans aucune modification.
class eMailBody { private $header = 'This is email header'; private $footer = 'This is email Footer'; public $body = ''; public function loadBody() { $this->body .= "This is Main Email body.<br />"; } }
Nous savons que Noël approche, alors supposons que je veuille saluer mes lecteurs dans mon prochain e-mail de newsletter. Je dois donc ajouter un message dans le corps de l'email avec une image qui a l'air bien.
Pour cela, je pourrais éditer directement dans mon cours de messagerie, mais je ne veux vraiment pas faire ça. Je peux donc implémenter l'héritage pour obtenir le même effet. Je crée une sous-classe distincte de la classe principale du corps de l'e-mail :
class christmasEmail extends eMailBody { public function loadBody() { parent::loadBody(); $this->body .= "Added Content for Xmas<br />"; } } $christmasEmail = new christmasEmail(); $christmasEmail->loadBody(); echo $christmasEmail->body;
J'ai donc terminé mon code et après quelques jours, j'ai voulu envoyer un e-mail avec mes vœux pour la nouvelle année. Nous pouvons utiliser la même approche que Noël.
class newYearEmail extends eMailBody { public function loadBody() { parent::loadBody(); $this->body .= "Added Content for New Year<br />"; } } $newYearEmail = new newYearEmail(); $newYearEmail->loadBody(); echo $newYearEmail->body;
Tout s'est bien passé sans aucun problème. Maintenant, disons que j'ai oublié de saluer mes visiteurs à ces deux occasions (Noël et Nouvel An) et que je souhaite envoyer les deux salutations dans un seul e-mail sans modifier aucun code dans la classe de base.
Votre esprit est immédiatement rempli des questions suivantes : le sous-classement et l'héritage seront-ils utiles ici ? Je suis favorable à cela, mais nous devons utiliser du code supplémentaire/inutile pour y parvenir. Nous pouvons utiliser des traits pour réaliser quelque chose de similaire à l’héritage multiple.
Le problème dont nous avons discuté dans la section précédente peut être résolu en implémentant le modèle décorateur.
Selon Wikipédia :
Le modèle Decorator (également connu sous le nom de Wrapper, une nomenclature alternative partagée avec le modèle Adapter) est un modèle de conception qui permet l'ajout statique ou dynamique de comportement à un seul objet sans affecter le comportement des autres objets. Même classe.
Dans la section précédente, nous avons vu que nous pouvons étendre les fonctionnalités/comportements à l'aide d'une sous-classe, mais lorsqu'il s'agit d'ajouter plusieurs fonctionnalités/comportements, cela devient verbeux et complexe. C’est là que nous devrions utiliser le modèle décorateur.
interface eMailBody { public function loadBody(); }
Il s'agit d'une interface simple utilisée pour garantir que certaines classes doivent implémenter les méthodes requises.
class eMail implements eMailBody { public function loadBody() { echo "This is Main Email body.<br />"; } }
C'est la classe principale qui génère le corps par défaut des e-mails, je l'utilise habituellement pour envoyer des e-mails. Cependant, ce dont j'ai besoin, c'est de modifier le contenu du corps en fonction de certaines occasions, mais pas de changer la classe de courrier électronique principale.
abstract class emailBodyDecorator implements eMailBody { protected $emailBody; public function __construct(eMailBody $emailBody) { $this->emailBody = $emailBody; } abstract public function loadBody(); }
Il s'agit de notre classe de décorateur principale, elle contient une référence à notre classe de courrier électronique principale et modifie son comportement si nécessaire. Nous définissons ici une méthode abstraite, loadBody
, que les enfants décorateurs doivent mettre en œuvre pour changer de comportement.
class christmasEmailBody extends emailBodyDecorator { public function loadBody() { echo 'This is Extra Content for Christmas<br />'; $this->emailBody->loadBody(); } } class newYearEmailBody extends emailBodyDecorator { public function loadBody() { echo 'This is Extra Content for New Year.<br />'; $this->emailBody->loadBody(); } }
Ici, nous avons créé deux sous-classes du décorateur principal qui effectuent réellement des changements de comportement sur notre classe de messagerie principale.
Nous avons créé tous les éléments requis. Tout ce que nous avons à faire est d'utiliser notre code et d'en profiter.
interface eMailBody { public function loadBody(); } class eMail implements eMailBody { public function loadBody() { echo "This is Main Email body.<br />"; } } abstract class emailBodyDecorator implements eMailBody { protected $emailBody; public function __construct(eMailBody $emailBody) { $this->emailBody = $emailBody; } abstract public function loadBody(); } class christmasEmailBody extends emailBodyDecorator { public function loadBody() { echo 'This is Extra Content for Christmas<br />'; $this->emailBody->loadBody(); } } class newYearEmailBody extends emailBodyDecorator { public function loadBody() { echo 'This is Extra Content for New Year.<br />'; $this->emailBody->loadBody(); } }
Nous allons maintenant utiliser ce cours de décorateur de différentes manières selon les besoins :
/* * Normal Email */ $email = new eMail(); $email->loadBody(); // Output This is Main Email body. /* * Email with Xmas Greetings */ $email = new eMail(); $email = new christmasEmailBody($email); $email->loadBody(); // Output This is Extra Content for Christmas This is Main Email body. /* * Email with New Year Greetings */ $email = new eMail(); $email = new newYearEmailBody($email); $email->loadBody(); // Output This is Extra Content for New Year. This is Main Email body. /* * Email with Xmas and New Year Greetings */ $email = new eMail(); $email = new christmasEmailBody($email); $email = new newYearEmailBody($email); $email->loadBody(); // Output This is Extra Content for New Year. This is Extra Content for Christmas This is Main Email body.
Nous pouvons voir que nous avons maintenant modifié le corps de l'e-mail sans modifier la classe principale de l'e-mail.
Chaque application que nous avons nécessite régulièrement des modifications et/ou des améliorations. Ainsi, dans ce cas, nous pouvons implémenter le modèle de conception du décorateur qui, à terme, améliorera la qualité du code et rendra notre code plus évolutif.
J'ai fait de mon mieux pour vous expliquer le motif du décorateur, mais si vous avez d'autres commentaires ou questions, n'hésitez pas à les ajouter au flux ci-dessous.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!