Patron Observer
Fait partie de la section Programmation Orientée Objet du Journey PHP de Coddy. Leçon 73 sur 91.
Le pattern Observateur est un pattern de conception comportemental qui établit une relation un-à-plusieurs entre les objets. Lorsqu’un objet (le sujet) change d’état, toutes ses dépendances (les observateurs) sont automatiquement informées et mises à jour.
Imaginez un abonnement à une newsletter. La newsletter est le sujet, et les abonnés sont les observateurs. Lorsqu’une nouvelle édition est publiée, tous les abonnés la reçoivent automatiquement sans que la newsletter ait besoin de connaître les détails de chaque abonné.
Voici une implémentation de base en PHP :
<?php
interface Observer {
public function update(string $message): void;
}
class Newsletter {
private array $subscribers = [];
public function subscribe(Observer $observer): void {
$this->subscribers[] = $observer;
}
public function publish(string $content): void {
foreach ($this->subscribers as $subscriber) {
$subscriber->update($content);
}
}
}
class EmailSubscriber implements Observer {
public function __construct(private string $email) {}
public function update(string $message): void {
echo "Sending to {$this->email}: $message\n";
}
}
$newsletter = new Newsletter();
$newsletter->subscribe(new EmailSubscriber("alice@example.com"));
$newsletter->subscribe(new EmailSubscriber("bob@example.com"));
$newsletter->publish("New article released!");
Sortie :
Sending to alice@example.com: New article released!
Sending to bob@example.com: New article released!Le modèle découple le sujet de ses observateurs. La classe Newsletter n’a pas besoin de savoir si elle avertit des abonnés par e-mail, des abonnés par SMS ou des services de notifications push. Elle appelle simplement update() sur tout élément qui implémente l’interface Observer. Cela permet d’ajouter facilement de nouveaux types d’observateurs sans modifier le code existant.
Défi
FacileConstruisons un système d’alerte de prix d’actions à l’aide du modèle Observer. Lorsque le prix d’une action change, tous les investisseurs inscrits doivent être automatiquement avertis : une application concrète parfaite de ce modèle.
Vous organiserez votre code sur quatre fichiers :
Observer.php: Définissez une interfaceObserveravec une seule méthodeupdate(string $stockName, float $price): void. Il s’agit du contrat que tous les observateurs doivent respecter pour recevoir les notifications.Investors.php: Incluez le fichier Observer et créez deux classes qui implémentent l’interface :EmailInvestor: Reçoit une adresse e-mail dans son constructeur (utilisez la promotion de constructeur). Sa méthodeupdate()affiche"Email to [email]: [stockName] is now $[price]"SmsInvestor: Reçoit un numéro de téléphone dans son constructeur. Sa méthodeupdate()affiche"SMS to [phone]: [stockName] is now $[price]"
Stock.php: Incluez le fichier Observer et créez une classeStockqui joue le rôle de sujet. Votre action doit :- Stocker le nom de l’action et son prix actuel (utilisez la promotion de constructeur pour le nom, initialisez le prix à
0.0) - Maintenir un tableau privé d’observateurs
- Disposer d’une méthode
subscribe(Observer $observer): voidpour ajouter des observateurs - Disposer d’une méthode
setPrice(float $price): voidqui met à jour le prix et avertit tous les observateurs
update()de chaque observateur avec le nom de l’action et son nouveau prix.- Stocker le nom de l’action et son prix actuel (utilisez la promotion de constructeur pour le nom, initialisez le prix à
main.php: Incluez les fichiers Investors et Stock. Vous recevrez trois entrées : un nom d’action, une adresse e-mail et un numéro de téléphone.Créez un
Stockavec le nom fourni. Inscrivez unEmailInvestoravec l’adresse e-mail et unSmsInvestoravec le numéro de téléphone.Définissez le prix de l’action à
150.50afin de déclencher les notifications pour tous les abonnés.
Le modèle Observer permet de découpler votre classe Stock des méthodes de notification spécifiques. Vous pourriez facilement ajouter ultérieurement un PushInvestor ou un SlackInvestor sans modifier du tout la classe Stock.
Essayez vous-même
<?php
require_once 'Investors.php';
require_once 'Stock.php';
// Lire les entrées
$stockName = trim(fgets(STDIN));
$email = trim(fgets(STDIN));
$phone = trim(fgets(STDIN));
// TODO: Créer un Stock avec le nom donné
// TODO: Abonner un EmailInvestor avec l'adresse e-mail
// TODO: Abonner un SmsInvestor avec le numéro de téléphone
// TODO: Définir le prix de l'action à 150.50 pour déclencher les notifications
?>Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses et objetsLe mot-clé $thisMéthodesPropriétésConstructeur (__construct)Destructeur (__destruct)Récapitulatif - Calculatrice simple4Héritage
Héritage de baseLe mot-clé parent::Redéfinition des méthodesLe mot-clé finalClasses abstraitesRécapitulatif – Hiérarchie des employés7Encapsulation
Public, Protected, PrivateModificateurs d’accès en profondeurAccesseurs et mutateursDissimulation de l’informationPromotion des constructeurs (8.0)Récapitulatif – Système de fiches étudiant10Concepts avancés de la POO
Composition ou héritageInjection de dépendancesClasses anonymesÉnumérations (PHP 8.1)Fibres (PHP 8.1)Approfondissement du clonage d’objetsGénérateurs et itérateurs13Patrons de conception – Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode modèlePatron ÉtatPatron CompositePatron Dépôt2Espaces de noms et chargement automatique
Introduction aux espaces de nomsLe mot-clé useNorme de chargement automatique PSR-4Autoloader de ComposerRécapitulatif - Projet organisé5Interfaces et contrats
Introduction aux interfacesImplémentation des interfacesImplémentation de plusieurs interfacesInterface ou classe abstraiteIndication de type avec les interfacesRécapitulatif - Calculateur de formes8Méthodes magiques
Introduction aux méthodes magiques__toString et __debugInfo__get, __set, __isset, __unset__call et __callStatic__clone et clonage d’objets__serialize et __unserializeRécapitulatif - Collection personnalisée3Propriétés de classe
Propriétés d’instance vs statiquesConstantes dans les classesMéthodes et propriétés statiquesPropriétés privées et protégéesPropriétés en lecture seule (PHP 8.1)Récapitulatif - Gestionnaire de comptes bancaires6Polymorphisme
Révision de la redéfinition des méthodesPolymorphisme via les interfacesAnnotations de type et types unionLiaison statique tardiveRécapitulatif - Processeur de paiements9Traits
Introduction aux traitsUtilisation de plusieurs traitsRésolution des conflits entre traitsMéthodes abstraites dans les traitsTraits par rapport à l’héritage12Patrons de conception – Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FactoryPatron ObserverPatron StrategyEntraînez-vous par vous-même : Compilateur PHP en ligne