Patron Observateur
Fait partie de la section Programmation Orientée Objet du Journey Dart de Coddy — leçon 92 sur 110.
Le patron Observateur établit une relation de un à plusieurs entre les objets : lorsqu'un objet (le sujet) change d'état, tous ses dépendants (observateurs) sont automatiquement notifiés. C'est parfait pour des scénarios tels que les mises à jour de l'interface utilisateur, les systèmes d'événements ou toute situation où plusieurs parties de votre application doivent réagir aux changements.
Le patron implique deux rôles clés : un Subject qui maintient une liste d'observateurs et les informe des changements, et des Observers qui s'enregistrent eux-mêmes et répondent aux mises à jour :
abstract class Observer {
void update(String message);
}
class NewsAgency {
final List<Observer> _observers = [];
String _latestNews = '';
void subscribe(Observer observer) {
_observers.add(observer);
}
void unsubscribe(Observer observer) {
_observers.remove(observer);
}
void publishNews(String news) {
_latestNews = news;
for (var observer in _observers) {
observer.update(_latestNews);
}
}
}
class NewsChannel implements Observer {
final String name;
NewsChannel(this.name);
@override
void update(String message) {
print('$name received: $message');
}
}
void main() {
var agency = NewsAgency();
var cnn = NewsChannel('CNN');
var bbc = NewsChannel('BBC');
agency.subscribe(cnn);
agency.subscribe(bbc);
agency.publishNews('Breaking news!');
// CNN a reçu : Breaking news!
// BBC a reçu : Breaking news!
}Lorsque publishNews est appelée, l'agence parcourt tous les observateurs abonnés et appelle leur méthode update. Les observateurs peuvent s'abonner ou se désabonner à tout moment, ce qui rend le système flexible et faiblement couplé - le sujet n'a pas besoin de connaître les types spécifiques de ses observateurs.
Défi
FacileConstruisons un système d'alerte de prix d'actions en utilisant le pattern Observer ! Vous allez créer un système où un téléscripteur d'actions (stock ticker) informe plusieurs investisseurs chaque fois que le prix change, permettant à chaque investisseur de réagir aux mises à jour du marché à sa manière.
Vous organiserez votre code en deux fichiers :
stock_system.dart: Créez votre système d'observateur ici :- Une classe abstraite
Investoravec une méthodevoid onPriceChange(String stockName, double price) - Une classe
DayTraderqui implémenteInvestor. Elle possède un champnameet sa méthodeonPriceChangeaffiche :[name] sees [stockName] at $[price] - Making quick trade! - Une classe
LongTermInvestorqui implémenteInvestor. Elle possède un champnameet sa méthodeonPriceChangeaffiche :[name] notes [stockName] at $[price] - Holding steady. - Une classe
StockTicker(le sujet) avec :- Un champ
String stockName - Une liste privée pour stocker les investisseurs abonnés
- Une méthode
subscribe(Investor investor)pour ajouter un investisseur - Une méthode
unsubscribe(Investor investor)pour supprimer un investisseur - Une méthode
updatePrice(double newPrice)qui notifie tous les investisseurs abonnés du nouveau prix
- Un champ
- Une classe abstraite
main.dart: Importez votre système d'actions et démontrez le pattern Observer en action :- Créez un
StockTickerpour une action nomméeDART - Créez un
DayTradernomméAliceet unLongTermInvestornomméBob - Abonnez les deux investisseurs au téléscripteur
- Mettez à jour le prix à
150.50(les deux investisseurs doivent être notifiés) - Affichez une ligne vide
- Désabonnez Alice du téléscripteur
- Mettez à jour le prix à
155.75(seul Bob doit être notifié maintenant)
- Créez un
Cela démontre comment le pattern Observer crée un système lâchement couplé - le StockTicker n'a pas besoin de savoir s'il notifie des traders de jour ou des investisseurs à long terme, il appelle simplement onPriceChange sur quiconque est abonné !
Sortie attendue :
Alice sees DART at $150.5 - Making quick trade!
Bob notes DART at $150.5 - Holding steady.
Bob notes DART at $155.75 - Holding steady.Aide-mémoire
Le pattern Observer (ou Observateur) établit une relation un-à-plusieurs où un sujet notifie tous ses observateurs lorsque son état change.
Le pattern comporte deux rôles clés :
- Sujet (Subject) : Maintient une liste d'observateurs et les informe des changements
- Observateur (Observer) : S'inscrit auprès du sujet et réagit aux mises à jour
Implémentation de base :
abstract class Observer {
void update(String message);
}
class Subject {
final List<Observer> _observers = [];
void subscribe(Observer observer) {
_observers.add(observer);
}
void unsubscribe(Observer observer) {
_observers.remove(observer);
}
void notifyObservers(String data) {
for (var observer in _observers) {
observer.update(data);
}
}
}
class ConcreteObserver implements Observer {
final String name;
ConcreteObserver(this.name);
@override
void update(String message) {
print('$name received: $message');
}
}Principaux avantages :
- Couplage faible entre le sujet et les observateurs
- Les observateurs peuvent s'abonner/se désabonner dynamiquement
- Le sujet n'a pas besoin de connaître les types spécifiques d'observateurs
Essayez vous-même
import 'stock_system.dart';
void main() {
// TODO: Créer un StockTicker pour une action nommée 'DART'
// TODO: Créer un DayTrader nommé 'Alice'
// TODO: Créer un LongTermInvestor nommé 'Bob'
// TODO: Abonner les deux investisseurs au ticker
// TODO: Mettre à jour le prix à 150.50 (les deux investisseurs doivent être notifiés)
// TODO: Afficher une ligne vide
// TODO: Désabonner Alice du ticker
// TODO: Mettre à jour le prix à 155.75 (seul Bob doit être notifié maintenant)
}
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
1Les bases de la POO
Fichiers externesBibliothèques et importsIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesVariables d'instanceBases des constructeursRécapitulatif - Calculatrice simple4Null Safety
Introduction à la Null SafetyNullable vs Non-NullableLes opérateurs ? et !Le mot-clé late et la Null SafetyLes opérateurs Null-AwareLa Null Safety dans les classesRécapitulatif - Système de profil utilisateur7Classes abstraites et Interfaces
Classes abstraitesMéthodes abstraitesInterfaces en DartInterfaces implicitesImplémentation vs ExtensionInterfaces multiplesRécapitulatif - Calculateur de formes10Collections et Génériques
Aperçu des List, Set et MapCollections Type-SafeClasses génériquesMéthodes génériquesContraintes de généricitéIterable & IteratorRécapitulatif - Stockage générique2Les constructeurs en Dart
Constructeur par défautConstructeurs nommésListes d'initialisationConstructeurs constantsConstructeurs factoryConstructeurs de redirectionRécapitulatif - Shape Builder5Encapsulation
Membres publics vs privésLa convention du préfixe _Visibilité au niveau de la bibliothèqueApprofondissement des Getters & SettersMasquage d'informationsRécapitulatif - Dossiers d'étudiants8Mixins
Introduction aux MixinsCréation de MixinsUtilisation de plusieurs MixinsLe mot-clé on dans les MixinsMixin vs HéritageMixin vs InterfaceRécapitulatif - Système Animal11Méthodes spéciales
Redéfinition de toString()Redéfinition de hashCode & ==Interface ComparableMéthode call()Redéfinition de noSuchMethodRécapitulatif - Collection personnalisée14Patrons de conception Partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron ObservateurPatron Stratégie3Propriétés de classe
Membres d'instance vs statiquesChamps Final & ConstVariables LateMéthodes et champs statiquesGetters et SettersRécapitulatif - Gestionnaire de compte bancaire6Héritage
Bases de l'héritageLe mot-clé superRedéfinition de méthodeL'annotation @overrideLe mot-clé final pour les classesConstructeurs et héritageRécapitulatif - Hiérarchie des employés9Polymorphisme
Bases du polymorphismePolymorphisme via les interfacesVérification de type à l'exécutionLes opérateurs is & asMot-clé covariantRécapitulatif - Processeur de paiement12POO Asynchrone
Futures & async/awaitBases des StreamsStream ControllersConstructeurs asynchronesL'asynchrone dans les méthodes de classeRécapitulatif - Data Fetcher15Patrons de conception Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode ModèlePatron ÉtatPatron CompositePatron Repository