Ein Entwurfsmuster ist eine Vorlage, die ein häufig wiederkehrendes Problem im Softwaredesign löst.

Das Beobachtermuster, auch bekannt als Publish-Subscribe-Muster, ist ein Verhaltensmuster. Es ermöglicht Ihnen, mehrere Objekte oder Abonnenten über jedes Ereignis zu benachrichtigen, das in dem von ihnen beobachteten Objekt veröffentlicht wird.

Hier erfahren Sie, wie Sie das Observer-Entwurfsmuster in TypeScript implementieren.

Das Beobachtermuster

Das Beobachtermuster funktioniert, indem es eine Eins-zu-Viele-Beziehung zwischen dem Herausgeber und seinen Abonnenten definiert. Wenn ein Ereignis im Herausgeber auftritt, benachrichtigt er alle Abonnenten dieses Ereignisses. Ein weit verbreitetes Beispiel für dieses Muster ist JavaScript-Ereignis-Listener.

Nehmen wir zum Kontext an, Sie bauen einen Bestandstracker, der die Anzahl der Produkte in Ihrem Geschäft verfolgt. In diesem Fall ist Ihr Geschäft der Betreff/Herausgeber und Ihr Inventar der Beobachter/Abonnent. Die Verwendung des Beobachter-Entwurfsmusters wäre in dieser Situation optimal.

instagram viewer

Im Beobachter-Entwurfsmuster muss Ihre Fachklasse drei Methoden implementieren:

  • Ein anfügen Methode. Diese Methode fügt dem Subjekt einen Beobachter hinzu.
  • A ablösen Methode. Diese Methode entfernt einen Beobachter von einem Subjekt.
  • A benachrichtigen/aktualisieren Methode. Diese Methode benachrichtigt die Beobachter des Subjekts, wenn sich der Zustand des Subjekts ändert.

Ihre Beobachterklasse muss eine Methode implementieren, die aktualisieren Methode. Diese Methode reagiert, wenn sich der Zustand des Objekts ändert.

Implementieren der Subjekt- und Beobachterklassen

Der erste Schritt zur Implementierung dieses Musters besteht darin, Schnittstellen für die Subjekt- und Beobachterklasse zu erstellen, um sicherzustellen, dass sie die richtigen Methoden implementieren:

// Betreff/Publisher-Schnittstelle
SchnittstelleThema{
AttachObserver (Beobachter: Beobachter): Leere;
disconnectObserver (Beobachter: Beobachter): Leere;
benachrichtigenObserver(): Leere;
}

// Observer/Subscriber-Schnittstelle
SchnittstelleBeobachter{
aktualisieren(Betreff: Betreff): Leere;
}

Die Schnittstellen im obigen Codeblock definieren die Methoden, die Ihre konkreten Klassen implementieren müssen.

Eine konkrete Themenklasse

Der nächste Schritt besteht darin, eine konkrete Subjektklasse zu implementieren, die die implementiert Thema Schnittstelle:

// Thema
KlasseSpeichernimplementiertThema{}

Als nächstes initialisieren Sie die Themas Zustand in der Speichern Klasse. Die Beobachter des Subjekts werden auf Änderungen dieses Zustands reagieren.

In diesem Fall ist der Zustand eine Zahl, und die Beobachter werden auf eine Erhöhung der Zahl reagieren:

// Status des Subjekts
Privatgelände numberOfProducts: Zahl;

Als nächstes initialisieren Sie ein Array von Beobachtern. Mit diesem Array behalten Sie die Beobachter im Auge:

// Beobachter initialisieren
Privatgelände Beobachter: Beobachter[] = [];

Möglicherweise finden Sie einige Implementierungen des Beobachtermusters using a Datenstruktur festlegen anstelle eines Arrays, um den Beobachter im Auge zu behalten. Die Verwendung eines Sets stellt sicher, dass derselbe Beobachter nicht zweimal erscheint. Wenn Sie stattdessen ein Array verwenden möchten, sollten Sie in Ihrem nach doppelten Beobachtern suchen anfügen Methode.

Als nächstes sollten Sie die implementieren Themas Methoden—anfügen, ablösen, Und benachrichtigen/aktualisieren– in deiner konkreten Klasse.

Zur Umsetzung der anfügen -Methode, überprüfen Sie zuerst, ob der Beobachter bereits angehängt ist, und geben Sie einen Fehler aus, wenn dies der Fall ist. Fügen Sie andernfalls den Beobachter mithilfe von dem Array hinzu JavaScript-Array-Methode, drücken:

// Beobachter anhängen
AttachObserver (Beobachter: Beobachter): Leere {
// Überprüfen Sie, ob der Beobachter bereits angehängt wurde
konst BeobachterExistiert = Das.observers.includes (Beobachter);

if (BeobachterExistiert) {
WurfneuFehler('Beobachter wurde bereits abonniert');
}

// Einen neuen Beobachter hinzufügen
Das.Beobachter.drücken(Beobachter);
}

Als nächstes implementieren Sie Ihre ablösen -Methode, indem Sie den Index finden und ihn mithilfe von JavaScript aus dem Array entfernen spleißen Methode.

Es kann Szenarien geben, in denen der Beobachter, den Sie zu trennen versuchen, bereits getrennt wurde oder überhaupt nicht abonniert wurde. Sie sollten diese Szenarien handhaben, indem Sie eine bedingte Anweisung hinzufügen, um zu überprüfen, ob sich der Beobachter im Array oder in der Menge befindet, je nach Fall.

// Beobachter(n) abtrennen
disconnectObserver (Beobachter: Beobachter): Leere {
Konsole.Protokoll(»Abtrennender Beobachter ${JSON.stringify (Beobachter)}`);
konst BeobachterIndex = Das.observers.indexOf (Beobachter);

if (beobachterindex -1) {
WurfneuFehler('Beobachter existiert nicht');
}

Das.Beobachter.spleißen(BeobachterIndex, 1);
Konsole.log ('Beobachter abgesetzt...');
}

Als nächstes implementieren Sie Ihre benachrichtigen/aktualisieren -Methode, indem Sie Ihre Beobachterliste durchlaufen und die aufrufen aktualisieren Methode von jedem:

// Beobachter benachrichtigen
benachrichtigenObserver(): Leere {
Konsole.log ('Beobachter benachrichtigen...');

für (konst Beobachter vonDas.Beobachter) {
Beobachter.update (Das);
}
}

Abschließend für die Thema Klasse, implementieren Sie eine Methode, die den Zustand manipuliert und dann die Beobachter über die Änderung benachrichtigt, indem sie ihre aufrufen benachrichtigen/aktualisieren Methode. Dieses Beispiel ist eine Vereinfachung, wie ein Subjekt eine Aktion ausführen und dann Beobachter informieren könnte:

// Zustand ändern und Beobachter benachrichtigen
newProduct (Produkte: Nummer): Leere {
Das.numberOfProducts += Produkte;
Konsole.log ('Neues Produkt zum Shop hinzugefügt');
Das.notifyObserver();
}

Konkrete Beobachterklassen

Erstellen Sie eine oder mehrere Beobachterklassen, um den Herausgeber zu abonnieren. Jede Beobachterklasse muss die implementieren Beobachter Schnittstelle.

Die Beobachterklassen implementieren a benachrichtigen/aktualisieren Methode, die nur das Subjekt, das sie beobachten, aufrufen sollte. Diese Methode sollte die gesamte Geschäftslogik enthalten, die Sie als Reaktion auf eine Änderung des Status des Subjekts ausführen müssen:

// Konkreter Beobachter 1
KlasseInventarimplementiertBeobachter{
aktualisieren(): Leere {
Konsole.log ('Neues Produkt zum Shop hinzugefügt, Lagerbestand aktualisieren...');
// Hier kommt die eigentliche Geschäftslogik hin...
}
}

// Konkreter Beobachter 2
KlasseKundeimplementiertBeobachter{
aktualisieren(): Leere {
Konsole.log ('Neues Produkt im Shop hinzugefügt, muss ich mir ansehen ...');
// Hier kommt die eigentliche Geschäftslogik hin...
}
}

Verwenden des Beobachtermusters

Um dieses Muster zu verwenden, instanziieren Sie die konkreten Subjekt- und Beobachterklassen. Sobald Sie dies getan haben, rufen Sie den Betreff an anfügen -Methode und übergeben Sie die Observer-Instanz als Argument. Als Antwort fügt das Subjekt diese Instanz seiner Beobachterliste hinzu:

// Subjekt und Beobachter instanziieren
konst speichern = neu Speichern();
konst Inventar = neu Inventar();
konst Kunde = neu Kunde()

// Objekte beim Herausgeber abonnieren
speichern.attachObserver(Inventar);
speichern.attachObserver(Kunde);
// Subjektstatus ändern
speichern.Neues Produkt(30);

Dieser Code simuliert eine Zustandsänderung. Die Änderung löst die Benachrichtigungsmethode auf der aus Thema Klasse. Diese Methode wiederum ruft die auf benachrichtigen Methode auf jeden seiner Beobachter. Jeder Beobachter führt dann seine eigene Geschäftslogik aus.

Sie sollten dieses Muster nur verwenden, wenn sich die Zustandsänderungen eines Objekts auf andere Objekte auswirken und die beteiligten Objekte unbekannt oder dynamisch sind.

Vorteile der Verwendung des Beobachtermusters

Die Verwendung dieses Musters in Ihrem Code ermöglicht es Ihnen, das Öffnen/Schließen-Prinzip beizubehalten. Sie können beliebig viele Abonnenten hinzufügen und zur Laufzeit Beziehungen zwischen Objekten herstellen, ohne den Code des Subjekts zu ändern.