Beobachtermuster
Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy. Lektion 92 von 110.
Das Observer-Pattern stellt eine Eins-zu-viele-Beziehung zwischen Objekten her: Wenn ein Objekt (das Subjekt) seinen Zustand ändert, werden alle seine Abhängigen (Beobachter) automatisch benachrichtigt. Dies ist ideal für Szenarien wie UI-Updates, Event-Systeme oder jede Situation, in der mehrere Teile Ihrer Anwendung auf Änderungen reagieren müssen.
Das Muster umfasst zwei zentrale Rollen: ein Subject, das eine Liste von Beobachtern verwaltet und sie über Änderungen benachrichtigt, sowie Observers, die sich registrieren und auf Aktualisierungen reagieren:
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 hat empfangen: Breaking news!
// BBC hat empfangen: Breaking news!
}Wenn publishNews aufgerufen wird, iteriert die Agentur durch alle abonnierten Observer und ruft deren update-Methode auf. Observer können sich jederzeit an- oder abmelden, was das System flexibel und lose gekoppelt macht – das Subjekt muss die spezifischen Typen seiner Observer nicht kennen.
Aufgabe
EinfachErstellen wir ein System zur Benachrichtigung über Aktienkurse mithilfe des Observer-Musters! Du erstellst ein System, in dem ein Börsenticker mehrere Investoren benachrichtigt, sobald sich der Kurs ändert, sodass jeder Investor auf seine eigene Weise auf Marktaktualisierungen reagieren kann.
Du organisierst deinen Code in zwei Dateien:
stock_system.dart: Erstelle hier dein Observer-System:- Eine abstrakte Klasse
Investormit einer Methodevoid onPriceChange(String stockName, double price) - Eine Klasse
DayTrader, dieInvestorimplementiert. Sie verfügt über ein Feldname, und ihre MethodeonPriceChangegibt Folgendes aus:[name] sees [stockName] at $[price] - Making quick trade! - Eine Klasse
LongTermInvestor, dieInvestorimplementiert. Sie verfügt über ein Feldname, und ihre MethodeonPriceChangegibt Folgendes aus:[name] notes [stockName] at $[price] - Holding steady. - Eine Klasse
StockTicker(das Subjekt) mit:- Ein Feld
String stockName - Eine private Liste zum Speichern abonnierter Investoren
- Eine Methode
subscribe(Investor investor), um einen Investor hinzuzufügen - Eine Methode
unsubscribe(Investor investor), um einen Investor zu entfernen - Eine Methode
updatePrice(double newPrice), die alle abonnierten Investoren über den neuen Kurs benachrichtigt
- Ein Feld
- Eine abstrakte Klasse
main.dart: Importiere dein Aktiensystem und demonstriere das Observer-Muster in Aktion:- Erstelle einen
StockTickerfür eine Aktie namensDART - Erstelle einen
DayTradernamensAliceund einenLongTermInvestornamensBob - Abonniere beide Investoren beim Ticker
- Aktualisiere den Kurs auf
150.50(beide Investoren sollten benachrichtigt werden) - Gib eine leere Zeile aus
- Beende Alices Abonnement beim Ticker
- Aktualisiere den Kurs auf
155.75(jetzt sollte nur Bob benachrichtigt werden)
- Erstelle einen
Dies zeigt, wie das Observer-Muster ein lose gekoppeltes System erstellt – der StockTicker muss nicht wissen, ob er Daytrader oder langfristige Investoren benachrichtigt; er ruft einfach onPriceChange bei jedem auf, der abonniert ist!
Erwartete Ausgabe:
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.Probier es selbst
import 'stock_system.dart';
void main() {
// TODO: Erstelle einen StockTicker für eine Aktie namens 'DART'
// TODO: Erstelle einen DayTrader namens 'Alice'
// TODO: Erstelle einen LongTermInvestor namens 'Bob'
// TODO: Melde beide Investoren beim ticker an
// TODO: Aktualisiere den Preis auf 150.50 (beide Investoren sollten benachrichtigt werden)
// TODO: Gib eine Leerzeile aus
// TODO: Melde Alice vom ticker ab
// TODO: Aktualisiere den Preis auf 155.75 (jetzt sollte nur Bob benachrichtigt werden)
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der OOP
Externe DateienBibliotheken & ImportsEinführung in die OOPKlassen vs. ObjekteDas Schlüsselwort thisMethodenInstanzvariablenGrundlagen von KonstruktorenRückblick – Einfacher Taschenrechner4Null-Sicherheit
Einführung in die Null-SicherheitNullable vs. Non-NullableDie Operatoren ? und !Late-Schlüsselwort und Null-SicherheitNull-bewusste OperatorenNull-Sicherheit in KlassenRückblick – Benutzers профilsystem7Abstrakte Klassen & Interfaces
Abstrakte KlassenAbstrakte MethodenInterfaces in DartImplizite InterfacesImplementieren vs. ErweiternMehrere InterfacesZusammenfassung – Formrechner10Collections & Generics
Übersicht über List, Set und MapTypsichere CollectionsGenerische KlassenGenerische MethodenGenerische EinschränkungenIterable & IteratorRückblick – Generischer Speicher13Fortgeschrittene OOP-Konzepte
Komposition vs. VererbungErweiterungsmethodenAufrufbare KlassenVersiegelte Klassen (Dart 3)Records (Dart 3)Muster & Matching (3.0)Enums mit Methoden16Projekt: Bibliotheksverwaltung
ProjektübersichtBuch- und Benutzerklassen2Konstruktoren in Dart
StandardkonstruktorBenannte KonstruktorenInitialisierungslistenKonstantenkonstruktorenFactory-KonstruktorenWeiterleitende KonstruktorenRückblick – Shape Builder5Kapselung
Öffentliche vs. private MemberDie _-Präfix-KonventionBibliotheksweite SichtbarkeitTiefergehende Getter & SetterInformationsverbergungRückblick – Studierendendaten8Mixins
Einführung in MixinsMixins erstellenMehrere Mixins verwendenDas Schlüsselwort „on“ in MixinsMixin vs. VererbungMixin vs. SchnittstelleRückblick – Tiersystem11Spezielle Methoden
toString()-ÜberschreibunghashCode- & ==-ÜberschreibungComparable-Schnittstellecall()-MethodenoSuchMethod-ÜberschreibungWiederholung – Benutzerdefinierte Collection14Entwurfsmuster Teil 1
Einführung in EntwurfsmusterSingleton-MusterFabrikmusterBeobachtermusterStrategiemuster17Abschließende Herausforderungen
E-Learning-PlattformBankingsystemSpielcharaktersystemFahrzeugvermietung3Klassen-Eigenschaften
Instanz- vs. statische MemberFinal- und Const-FelderLate-VariablenStatische Methoden und FelderGetter und SetterRückblick – Bankkontoverwaltung6Vererbung
Grundlegende VererbungDas Schlüsselwort superMethodenüberschreibungDie Annotation @overrideDas Schlüsselwort final für KlassenKonstruktoren und VererbungZusammenfassung – Mitarbeiterhierarchie9Polymorphismus
Grundlagen des PolymorphismusPolymorphismus über InterfacesLaufzeit-TypüberprüfungDie Operatoren is & asCovariant-SchlüsselwortZusammenfassung – ZahlungsprozessorÜbe selbstständig: Online-Dart-Compiler