Patron Observateur
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 68 sur 87.
Le Patron d'Observation (Observer Pattern) est un patron de conception comportemental qui établit une relation de un à plusieurs entre les objets. Lorsqu'un objet (le sujet) change d'état, tous ses dépendants (les observateurs) sont automatiquement notifiés et mis à jour. Considérez cela comme un abonnement à une newsletter : les abonnés reçoivent des mises à jour chaque fois qu'un nouveau contenu est publié.
Le patron comporte deux composants principaux : un sujet qui maintient une liste d'observateurs et les informe des changements, et des observateurs qui définissent une méthode de mise à jour pour répondre aux notifications :
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
class NewsPublisher {
private List<Observer> subscribers = new ArrayList<>();
public void subscribe(Observer observer) {
subscribers.add(observer);
}
public void unsubscribe(Observer observer) {
subscribers.remove(observer);
}
public void publish(String news) {
for (Observer subscriber : subscribers) {
subscriber.update(news);
}
}
}
class EmailSubscriber implements Observer {
private String email;
public EmailSubscriber(String email) {
this.email = email;
}
public void update(String message) {
System.out.println("Email to " + email + ": " + message);
}
}Lorsque l'éditeur publie des actualités, tous les abonnés sont notifiés automatiquement :
NewsPublisher publisher = new NewsPublisher();
publisher.subscribe(new EmailSubscriber("alice@mail.com"));
publisher.subscribe(new EmailSubscriber("bob@mail.com"));
publisher.publish("Breaking news!");
// Sortie :
// Email à alice@mail.com : Breaking news!
// Email à bob@mail.com : Breaking news!Le patron de conception Observateur favorise un couplage faible — le sujet n'a pas besoin de connaître les classes concrètes de ses observateurs, seulement qu'ils implémentent l'interface Observer. Cela permet d'ajouter facilement de nouveaux types d'observateurs sans modifier le sujet.
Défi
FacileConstruisons un système d'alerte de cours boursiers en utilisant le modèle Observer (Observateur) ! Vous allez créer un système où un téléscripteur boursier (stock ticker) informe plusieurs investisseurs chaque fois que le prix de l'action change, permettant à chaque investisseur de réagir aux mises à jour de prix à sa manière.
Vous organiserez votre code sur quatre fichiers :
Observer.java: Définissez l'interfaceObserverque tous les investisseurs implémenteront. Elle doit déclarer une seule méthodeupdate(String stockName, double price)que les observateurs utilisent pour recevoir des notifications sur les changements de prix.StockTicker.java: Créez la classe sujet qui maintient une liste d'observateurs et les informe des changements de prix. VotreStockTickerdoit avoir :Un champ String privé pour le nom de l'action (défini via le constructeur).
Un champ double privé pour le prix actuel (initialement 0).
Une liste privée pour stocker les observateurs abonnés.
Une méthode
subscribe(Observer observer)qui ajoute un observateur à la liste.Une méthode
unsubscribe(Observer observer)qui supprime un observateur de la liste.Une méthode
setPrice(double price)qui met à jour le prix puis informe tous les observateurs en appelant leur méthodeupdateavec le nom de l'action et le nouveau prix.Investors.java: Créez deux types différents d'investisseurs qui implémentent l'interfaceObserver:DayTrader- possède un champ de nom privé défini via le constructeur. Lors de la mise à jour, affiche[name] received alert: [stockName] is now $[price] - Making quick trade!LongTermInvestor- possède un champ de nom privé défini via le constructeur. Lors de la mise à jour, affiche[name] received alert: [stockName] is now $[price] - Holding steady.Formatez le prix avec deux décimales.
Main.java: Rassemblez votre système d'observateurs ! Vous recevrez trois entrées : le nom de l'action (String), la première mise à jour de prix (double) et la deuxième mise à jour de prix (double).Créez un
StockTickeravec le nom d'action donné. Créez unDayTradernommé"Alice"et unLongTermInvestornommé"Bob", et abonnez les deux au téléscripteur.Définissez le prix sur la première valeur d'entrée (tous les observateurs sont informés). Ensuite, désabonnez Alice. Enfin, définissez le prix sur la deuxième valeur d'entrée (seul Bob devrait être informé cette fois).
Vous recevrez trois entrées dans l'ordre : le nom de l'action (String), le premier prix (double), le deuxième prix (double).
Ce défi démontre la puissance du modèle Observer : le StockTicker ne sait rien des types d'investisseurs spécifiques — il sait simplement qu'ils implémentent Observer. Lorsque vous désabonnez Alice, elle cesse de recevoir des mises à jour tandis que Bob continue d'être informé. Ce couplage lâche facilite l'ajout de nouveaux types d'investisseurs sans modifier le téléscripteur !
Aide-mémoire
Le Pattern Observateur est un patron de conception comportemental qui établit une relation de un à plusieurs entre des objets. Lorsqu'un objet (le sujet) change d'état, tous ses dépendants (les observateurs) sont automatiquement notifiés et mis à jour.
Le patron implique deux composants principaux :
- Sujet : Maintient une liste d'observateurs et les informe des changements
- Observateurs : Définissent une méthode de mise à jour pour répondre aux notifications
Structure de base :
import java.util.ArrayList;
import java.util.List;
interface Observer {
void update(String message);
}
class Subject {
private List<Observer> observers = new ArrayList<>();
public void subscribe(Observer observer) {
observers.add(observer);
}
public void unsubscribe(Observer observer) {
observers.remove(observer);
}
public void notifyObservers(String message) {
for (Observer observer : observers) {
observer.update(message);
}
}
}
class ConcreteObserver implements Observer {
public void update(String message) {
// Réagir à la notification
}
}Exemple d'utilisation :
Subject subject = new Subject();
subject.subscribe(new ConcreteObserver());
subject.notifyObservers("State changed!");
// Tous les observateurs abonnés reçoivent la mise à jourLe Pattern Observateur favorise le couplage faible — le sujet n'a pas besoin de connaître les classes concrètes de ses observateurs, seulement qu'ils implémentent l'interface Observer. Cela facilite l'ajout de nouveaux types d'observateurs sans modifier le sujet.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String stockName = scanner.nextLine();
double firstPrice = scanner.nextDouble();
double secondPrice = scanner.nextDouble();
// TODO: Créer un StockTicker avec le nom d'action donné
// TODO: Créer un DayTrader nommé "Alice"
// TODO: Créer un LongTermInvestor nommé "Bob"
// TODO: Abonner Alice et Bob au ticker
// TODO: Définir le prix à firstPrice (les deux observateurs sont notifiés)
// TODO: Désabonner Alice
// TODO: Définir le prix à secondPrice (seul Bob est notifié)
scanner.close();
}
}
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 vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur