Wzorzec Observer
Część sekcji Programowanie obiektowe ścieżki Dart w Coddy. Lekcja 92 z 110.
Wzorzec Obserwator ustanawia relację jeden-do-wielu między obiektami: gdy jeden obiekt (podmiot) zmienia stan, wszystkie obiekty od niego zależne (obserwatorzy) są automatycznie powiadamiane. Sprawdza się doskonale w takich sytuacjach jak aktualizacje interfejsu użytkownika, systemy zdarzeń lub wszędzie tam, gdzie wiele części aplikacji musi reagować na zmiany.
Wzorzec obejmuje dwie kluczowe role: podmiot, który przechowuje listę obserwatorów i powiadamia ich o zmianach, oraz obserwatorów, którzy się rejestrują i reagują na aktualizacje:
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 otrzymało: Pilna wiadomość!
// BBC otrzymało: Pilna wiadomość!
}Gdy wywoływana jest funkcja publishNews, agencja przechodzi przez wszystkich subskrybujących obserwatorów i wywołuje ich metodę update. Obserwatorzy mogą w dowolnym momencie subskrybować lub rezygnować z subskrypcji, dzięki czemu system jest elastyczny i luźno powiązany — podmiot nie musi znać konkretnych typów swoich obserwatorów.
Wyzwanie
ŁatwyZbudujmy system alertów o cenach akcji, korzystając ze wzorca Obserwator! Utworzysz system, w którym notowania akcji powiadamiają wielu inwestorów za każdym razem, gdy zmieni się cena, umożliwiając każdemu inwestorowi reagowanie na aktualizacje rynkowe na swój sposób.
Podzielisz kod na dwa pliki:
stock_system.dart: tutaj utwórz system obserwatorów:- Klasa abstrakcyjna
Investorz metodąvoid onPriceChange(String stockName, double price) - Klasa
DayTrader, która implementujeInvestor. Ma polename, a jej metodaonPriceChangewypisuje:[name] sees [stockName] at $[price] - Making quick trade! - Klasa
LongTermInvestor, która implementujeInvestor. Ma polename, a jej metodaonPriceChangewypisuje:[name] notes [stockName] at $[price] - Holding steady. - Klasa
StockTicker(podmiot) z:- Polem
String stockName - Prywatną listą do przechowywania subskrybujących inwestorów
- Metodą
subscribe(Investor investor)dodającą inwestora - Metodą
unsubscribe(Investor investor)usuwającą inwestora - Metodą
updatePrice(double newPrice), która powiadamia wszystkich subskrybujących inwestorów o nowej cenie
- Polem
- Klasa abstrakcyjna
main.dart: zaimportuj system notowań akcji i pokaż wzorzec Obserwator w działaniu:- Utwórz
StockTickerdla akcji o nazwieDART - Utwórz
DayTradero nazwieAliceiLongTermInvestoro nazwieBob - Zasubskrybuj obu inwestorów do notowań
- Zaktualizuj cenę do
150.50(obaj inwestorzy powinni otrzymać powiadomienie) - Wypisz pusty wiersz
- Usuń subskrypcję Alice do notowań
- Zaktualizuj cenę do
155.75(teraz powiadomienie powinien otrzymać tylko Bob)
- Utwórz
To pokazuje, jak wzorzec Obserwator tworzy luźno powiązany system — StockTicker nie musi wiedzieć, czy powiadamia day traderów, czy inwestorów długoterminowych; po prostu wywołuje onPriceChange u każdego, kto subskrybuje!
Oczekiwany wynik:
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.Spróbuj swoich sił
import 'stock_system.dart';
void main() {
// TODO: Utwórz StockTicker dla akcji o nazwie 'DART'
// TODO: Utwórz DayTrader o imieniu 'Alice'
// TODO: Utwórz LongTermInvestor o imieniu 'Bob'
// TODO: Zasubskrybuj obu inwestorów do tickera
// TODO: Zaktualizuj cenę do 150.50 (obaj inwestorzy powinni otrzymać powiadomienie)
// TODO: Wypisz pusty wiersz
// TODO: Usuń subskrypcję Alice z tickera
// TODO: Zaktualizuj cenę do 155.75 (teraz tylko Bob powinien otrzymać powiadomienie)
}
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Podstawy OOP
Pliki zewnętrzneBiblioteki i importyWprowadzenie do OOPKlasy a obiektySłowo kluczowe thisMetodyZmienne instancjiPodstawy konstruktorówPowtórka – prosty kalkulator4Bezpieczeństwo wartości null
Wprowadzenie do bezpieczeństwa wartości nullTypy dopuszczające null i niedopuszczające nullOperatory ? i !Słowo kluczowe late a bezpieczeństwo wartości nullOperatory uwzględniające nullBezpieczeństwo wartości null w klasachPodsumowanie — system profili użytkowników7Klasy abstrakcyjne i interfejsy
Klasy abstrakcyjneMetody abstrakcyjneInterfejsy w DartInterfejsy niejawneImplementowanie a rozszerzanieWiele interfejsówPowtórka — kalkulator kształtów10Kolekcje i typy generyczne
Przegląd List, Set i MapKolekcje bezpieczne typowoKlasy generyczneMetody generyczneOgraniczenia typów generycznychIterable i IteratorPowtórka — generyczne przechowywanie danych13Zaawansowane koncepcje OOP
Kompozycja a dziedziczenieMetody rozszerzająceKlasy wywoływalneKlasy zapieczętowane (Dart 3)Rekordy (Dart 3)Wzorce i dopasowywanie (3.0)Typy wyliczeniowe z metodami16Projekt: Zarządzanie biblioteką
Omówienie projektuKlasy książek i użytkowników2Konstruktory w Dart
Konstruktor domyślnyKonstruktory nazwaneListy inicjalizująceKonstruktory stałeKonstruktory fabryczneKonstruktory przekierowującePodsumowanie — budowanie kształtów5Hermetyzacja
Elementy publiczne a prywatneKonwencja prefiksu _Prywatność na poziomie bibliotekiGettery i settery — szczegółowoUkrywanie informacjiPodsumowanie — dane uczniów8Domieszki
Wprowadzenie do domieszekTworzenie domieszekKorzystanie z wielu domieszekSłowo kluczowe on w domieszkachDomieszka a dziedziczenieDomieszka a interfejsPodsumowanie – system zwierząt11Metody specjalne
Nadpisanie toString()Nadpisanie hashCode i ==Interfejs ComparableMetoda call()Nadpisanie noSuchMethodPodsumowanie — własna kolekcja14Wzorce projektowe, część 1
Wprowadzenie do wzorców projektowychWzorzec SingletonWzorzec FactoryWzorzec ObserverWzorzec Strategy3Właściwości klas
Elementy instancji a elementy statycznePola final i constZmienne inicjalizowane z opóźnieniemMetody i pola statyczneGettery i setteryPowtórzenie – menedżer kont bankowych6Dziedziczenie
Podstawy dziedziczeniaSłowo kluczowe superPrzesłanianie metodAdnotacja @overrideSłowo kluczowe final dla klasKonstruktory i dziedziczeniePowtórzenie – hierarchia pracowników9Polimorfizm
Podstawy polimorfizmuPolimorfizm za pomocą interfejsówSprawdzanie typu w czasie działaniaOperatory is i asSłowo kluczowe covariantPodsumowanie — procesor płatnościPoćwicz samodzielnie: Kompilator Dart online