Wzorzec projektowy to szablon, który rozwiązuje często powtarzający się problem w projektowaniu oprogramowania.
Wzorzec obserwatora, znany również jako wzorzec publikowania-subskrybowania, jest wzorcem behawioralnym. Pozwala powiadomić wiele obiektów lub subskrybentów o każdym zdarzeniu, które jest publikowane w obserwowanym przez nich obiekcie.
Tutaj dowiesz się, jak zaimplementować wzorzec projektowy obserwatora w TypeScript.
Wzór obserwatora
Wzorzec obserwatora polega na zdefiniowaniu relacji jeden-do-wielu między wydawcą a jego subskrybentami. Gdy w wydawcy wystąpi zdarzenie, powiadomi on wszystkich subskrybentów o tym zdarzeniu. Jednym z powszechnych przykładów tego wzorca jest Detektory zdarzeń JavaScript.
Dla kontekstu załóżmy, że budujesz narzędzie do śledzenia zapasów, które śledzi liczbę produktów w Twoim sklepie. W tym przypadku Twój sklep jest podmiotem/wydawcą, a Twój asortyment obserwatorem/subskrybentem. Wykorzystanie wzorca projektowego obserwatora byłoby w tej sytuacji optymalne.
We wzorcu projektowym obserwatora klasa przedmiotowa musi zaimplementować trzy metody:
- Jakiś przytwierdzać metoda. Ta metoda dodaje obserwatora do tematu.
- A odłączyć metoda. Ta metoda usuwa obserwatora z tematu.
- A powiadomić/zaktualizować metoda. Ta metoda powiadamia obserwatorów podmiotu o zmianie stanu podmiotu.
Twoja klasa obserwatora musi zaimplementować jedną metodę, the aktualizacja metoda. Ta metoda reaguje, gdy następuje zmiana stanu podmiotu.
Implementacja klas podmiotu i obserwatora
Pierwszym krokiem do wdrożenia tego wzorca jest stworzenie interfejsów dla klasy podmiotu i obserwatora, aby upewnić się, że implementują one poprawne metody:
// Interfejs podmiotu/wydawcy
interfejsTemat{
attachObserver (obserwator: Obserwator): próżnia;
odłącz Obserwatora (obserwator: Obserwator): próżnia;
powiadomić Obserwatora(): próżnia;
}
// Interfejs obserwatora/subskrybenta
interfejsObserwator{
aktualizacja(temat: temat): próżnia;
}
Interfejsy w powyższym bloku kodu definiują metody, które muszą implementować twoje konkretne klasy.
Konkretna klasa przedmiotowa
Następnym krokiem jest wdrożenie konkretnej klasy przedmiotowej, która implementuje Temat interfejs:
// Temat
klasaSklepprzyboryTemat{}
Następnie zainicjuj Tematstan w Sklep klasa. Obserwatorzy podmiotu będą reagować na zmiany tego stanu.
W tym przypadku stan jest liczbą, a obserwatorzy zareagują na wzrost liczby:
// Stan podmiotu
prywatny liczbaProduktów: liczba;
Następnie zainicjuj tablicę obserwatorów. Ta tablica to sposób, w jaki będziesz śledzić obserwatorów:
// inicjowanie obserwatorów
prywatny obserwatorzy: Obserwator[] = [];
Możesz znaleźć kilka implementacji wzorca obserwatora używającego a Ustaw strukturę danych zamiast tablicy do śledzenia obserwatora. Użycie zestawu zapewni, że ten sam obserwator nie pojawi się dwa razy. Jeśli zamiast tego chcesz użyć tablicy, powinieneś sprawdzić zduplikowanych obserwatorów w swoim przytwierdzać metoda.
Następnie należy zaimplementować Tematmetody —przytwierdzać, odłączyć, I powiadomić/zaktualizować— w twojej konkretnej klasie.
Aby wdrożyć przytwierdzać metoda, najpierw sprawdź, czy obserwator jest już podłączony i zgłoś błąd, jeśli tak jest. W przeciwnym razie dodaj obserwatora do tablicy za pomocą metody Metoda tablicy JavaScript, naciskać:
// Dołączanie obserwatora(ów)
attachObserver (obserwator: Obserwator): próżnia {
// Sprawdź, czy obserwator został już dołączony
konst obserwatorIstnieje = Ten.observers.includes (obserwator);if (obserwatoristnieje) {
rzucićnowyBłąd(„Obserwator został już zasubskrybowany”);
}
// Dodaj nowego obserwatora
Ten.obserwatorzy.naciskać(obserwator);
}
Następnie zaimplementuj swoje odłączyć metodą, znajdując indeks i usuwając go z tablicy za pomocą JavaScript splatać metoda.
Mogą wystąpić scenariusze, w których obserwator, którego próbujesz odłączyć, został już odłączony lub nie został zasubskrybowany. Powinieneś poradzić sobie z tymi scenariuszami, dodając instrukcję warunkową, aby sprawdzić, czy obserwator znajduje się w tablicy lub zestawie, w zależności od przypadku.
// Odłączanie obserwatora(ów)
odłącz Obserwatora (obserwator: Obserwator): próżnia {
konsola.dziennik(`Odłączanie obserwatora ${JSON.stringify (obserwator)}`);
konst indeks obserwatora = Ten.observers.indexOf (obserwator);if (indeksobserwatora -1) {
rzucićnowyBłąd(„Obserwator nie istnieje”);
}
Ten.obserwatorzy.splatać(indeks obserwatora, 1);
log konsoli ('Obserwator odłączony...');
}
Następnie zaimplementuj swoje powiadomić/zaktualizować poprzez zapętlenie listy obserwatorów i wywołanie metody aktualizacja metoda każdego z nich:
// Powiadamianie obserwatorów
powiadomić Obserwatora(): próżnia {
log konsoli ('Powiadamianie obserwatorów...');
Do (konst obserwator zTenobserwatorzy) {
obserwator.aktualizacja(Ten);
}
}
Wreszcie dla Temat class, zaimplementuj metodę, która manipuluje stanem, a następnie powiadamia obserwatorów o zmianie, wywołując ich powiadomić/zaktualizować metoda. Ten przykład jest uproszczeniem tego, jak podmiot może wykonać akcję, a następnie poinformować obserwatorów:
// Zmiana stanu i powiadamianie obserwatorów
nowyProdukt (produkty: liczba): próżnia {
Ten.liczba produktów += produkty;
log konsoli ('Nowy produkt dodany do sklepu');
Ten.notifyObserver();
}
Konkretne klasy obserwatorów
Utwórz klasę lub klasy obserwatorów, aby zasubskrybować wydawcę. Każda klasa obserwatorów musi implementować Obserwator interfejs.
Klasy obserwatorów zaimplementują a powiadomić/zaktualizować metodę, którą powinien wywołać tylko podmiot, który obserwują. Ta metoda powinna zawierać całą logikę biznesową potrzebną do uruchomienia w odpowiedzi na zmianę stanu podmiotu:
// Konkretny obserwator 1
klasaSpisprzyboryObserwator{
aktualizacja(): próżnia {
log konsoli ('Nowy produkt dodany do sklepu, aktualizacja stanów magazynowych...');
// Rzeczywista logika biznesowa idzie tutaj...
}
}
// Konkretny obserwator 2
klasaKlientprzyboryObserwator{
aktualizacja(): próżnia {
log konsoli ('Nowy produkt dodany do sklepu, muszę iść sprawdzić...');
// Rzeczywista logika biznesowa idzie tutaj...
}
}
Korzystanie ze wzorca obserwatora
Aby użyć tego wzorca, utwórz konkretną klasę podmiotu i obserwatora. Gdy to zrobisz, zadzwoń do podmiotu przytwierdzać metodę i przekazać instancję Observer jako argument. W odpowiedzi podmiot doda tę instancję do swojej listy obserwatorów:
// Tworzenie instancji podmiotu i obserwatora
konst sklep = nowy Sklep();
konst inwentarz = nowy Spis();
konst klient = nowy Klient()
// Subskrybowanie obiektów do wydawcy
sklep.attachObserver(spis);
sklep.attachObserver(klient);
// Zmiana stanu podmiotu
sklep.nowy produkt(30);
Ten kod symuluje zmianę stanu. Zmiana spowoduje wyzwolenie metody powiadamiania na Temat klasa. Ta metoda z kolei wywołuje metodę notyfikować metodę na każdego ze swoich obserwatorów. Każdy obserwator będzie wtedy uruchamiał własną logikę biznesową.
Wzorca tego należy używać tylko wtedy, gdy zmiany stanu jednego obiektu wpływają na inne obiekty, a zestaw obiektów, których to dotyczy, jest nieznany lub dynamiczny.
Zalety korzystania ze wzorca obserwatora
Użycie tego wzorca w kodzie pozwala zachować zasadę otwórz/zamknij. Możesz dodać dowolną liczbę subskrybentów i ustanowić relacje między obiektami w czasie wykonywania, bez zmiany kodu podmiotu.