Schreiben Sie ein Publish-Subscribe-Modell mit JS

Schreiben Sie ein Publish-Subscribe-Modell mit JS

Was ist das Publish-Subscribe-Modell? Kannst du es mit der Hand schreiben? Unterscheidet es sich vom Beobachtermuster? ...

1. Szeneneinführung

Schauen wir uns ein Szenario wie dieses an:

Angenommen, es gibt eine soziale Plattform mit einer berühmten Person namens Nami

Nami ist sehr talentiert und vielseitig. Derzeit hat sie zwei Fähigkeiten: Lieder schreiben und Videos drehen.

Sie wird diese Arbeiten auf der Plattform veröffentlichen. Fans, die ihr folgen, erhalten diese Inhalte

Jetzt hat er 3 Fans, nämlich: Luffy, Zoro, Sanji

Jedes Mal, wenn Nami ein Werk veröffentlicht, werden die auf den Konten der drei Fans eingegangenen Nachrichten aktualisiert.

Lassen Sie es uns nun in Code ausdrücken:

const Ruffy = {
  Update: Funktion (Lieder, Videos) {
    console.log(Lieder, Videos);
  },
};
const zoro = {
  Update: Funktion (Lieder, Videos) {
    console.log(Lieder, Videos);
  },
};
const sanji = {
  Update: Funktion (Lieder, Videos) {
    console.log(Lieder, Videos);
  },
};

const nami = {
  // Diese Methode wird aufgerufen, wenn Namis Arbeit aktualisiert wird workUpdate: function () {
    // Werke abrufen const songs = this.getSongs();
    const videos = this.getVideos();

    //Kontoaktualisierung luffy.update(songs, videos);
    zoro.update(Lieder, Videos);
    sanji.update(Lieder, Videos);
  },
  getSongs: Funktion () {
    gib "mp3" zurück;
  },
  getVideos: Funktion () {
    gib "mp4" zurück;
  },
};

Jetzt kommt das Problem

  • Wenn Nami einen weiteren Fan, Robin bekommt, muss ich ein robin -Objekt hinzufügen und workUpdate ändern.
  • Wenn Nami eine neue Fähigkeit hat: Romane schreiben, muss ich sowohl workUpdate Funktion als auch die update Methode in jedem Fan-Objekt ändern, da der Parameter um eins erhöht wurde.

Irgendein Problem gefunden?

Die Kopplung zwischen dem Fan-Objekt und dem Influencer-Objekt ist zu hoch, sodass eine unabhängige Skalierung der einzelnen Objekte schwierig ist.

2 Code-Optimierung

2.1 Lösen Sie das Problem der zunehmenden Fans

Lösen wir zuerst das erste Problem, damit wir workUpdate beim Hinzufügen von Fans nicht ändern müssen.

Zuerst abstrahieren wir das „große V“ in eine Klasse „Star“, verwenden das Array fans , um die Lüfterliste zu speichern, und fügen eine Methode addFans hinzu, um Lüfter hinzuzufügen.

Klasse Stern {
  Konstruktor() {
    diese.fans = [];
  }
  addFans(Fan) {
    this.fans.push(Lüfter)
  }
  arbeitsUpdate() {
    const songs = this.getSongs();
    const videos = this.getVideos();
    this.fans.forEach((item) => item.update(songs, videos));
  }
  getSongs() {
    gib "MP3" zurück;
  }
  getVideos() {
    gib "MP4" zurück;
  }
}

Als nächstes abstrahieren wir „Fans“ in eine Klasse Fan. Beim Erstellen eines Fan-Objekts übergeben wir das „große V“-Objekt und rufen die addFans Methode des großen V auf, um es der Fan-Liste hinzuzufügen.

Klasse Fan {
  Konstruktor(Name, Stern) {
    dieser.name = Name
    dieser.Stern = Stern
    dies.star.addFans(dies)
  }
  Update (Lieder, Videos) {
    console.log(Lieder, Videos);
  }
}


Jetzt müssen wir den Code nicht mehr ändern, um Fans hinzuzufügen

const nami = neuer Stern()
const luffy = neuer Fan("luffy", nami);
const zoro = neuer Fan("zoro", nami);
const sanji = neuer Fan("sanji", nami);
const robin = neuer Fan("robin", nami);
nami.workUpdate()

2.2 Lösen Sie das Problem des Hinzufügens von Werken

Wir fügen ein works Array hinzu, um die Works von Big V zu speichern, und fügen ihm get und set Methoden hinzu.

Klasse Stern {
  Konstruktor() {
    diese.fans = [];
    dies.funktioniert = [];
  }
  addFans(Fan) {
    dies.fans.push(Ventilator);
  }
  setWorks(Arbeit) {
    dies.funktioniert.push(arbeit);
    // Rufen Sie nach dem Hinzufügen der Arbeit die Aktualisierungsmethode this.workUpdate(); auf.
  }
  getWorks() {
    gib dies zurück.funktioniert;
  }
  arbeitsUpdate() {
    diese.fans.forEach((item) => item.update());
  }
}


Passen Sie die Fan-Klasse entsprechend an:

Klasse Fan {
  Konstruktor(Name, Stern) {
    dieser.name = Name
    dieser.Stern = Stern
    dies.star.addFans(dies)
  }
  aktualisieren() {
    Konsole.log(`${this.name}:${this.star.getWorks()}`)
  }
}


Jetzt müssen große Vs den Code nicht mehr ändern, um Werke hinzuzufügen:

const nami = neuer Stern();
nami.setWorks('Lied')
nami.setWorks('Video')
nami.setWorks('Roman')
const luffy = neuer Fan("luffy", nami);
const zoro = neuer Fan("zoro", nami);
const sanji = neuer Fan("sanji", nami);
nami.workUpdate();

3 Beobachtermuster

Wie Sie sehen, besteht im obigen Beispiel eine Eins-zu-viele-Abhängigkeitsbeziehung zwischen einem nami Objekt und mehreren Fan-Objekten. Wenn das nami Objekt ein Arbeitsupdate hat, erhalten alle Fan-Objekte, die ihm folgen, eine Benachrichtigung.

Tatsächlich ist dies der Beobachtermodus

Beobachtermuster: Definiert eine Eins-zu-viele-Abhängigkeitsbeziehung zwischen Objekten. Wenn sich der Status eines Objekts ändert, werden alle davon abhängigen Objekte benachrichtigt und automatisch aktualisiert.

Wir abstrahieren den Code in 2.2 weiter:

Die „Fans“ werden als Observer betrachtet, und das „große V“ wird als Beobachtungsobjekt, sogenanntes Subject , angesehen.

Subject verwaltet eine Beobachterliste observerList (ursprünglich ein Fans-Array). Wenn sich der Status Subject ändert (ursprüngliches Arbeitsupdate), werden alle Beobachter durch Aufrufen der Methode „Benachrichtigung (ursprüngliches workUpdate )“ benachrichtigt und ihre update werden ausgeführt.

Der spezifische Code lautet wie folgt:

//Beobachter: Betreffklasse Betreff {
  Konstruktor() {
    diese.Beobachterliste = [];
    // Stellt den Subjektstatus dar this.state = 0;
  }
  addObserver(Beobachter) {
    dies.observerList.push(Beobachter);
  }
  // Den Designstatus ändern setState(state) {
    dieser.zustand = zustand;
    //Nach der Statusänderung alle Beobachter benachrichtigen this.notify();
  }
  getState() {
    gib diesen Status zurück;
  }
  benachrichtigen() {
    this.observerList.forEach((Beobachter) => Beobachter.update());
  }
}

//Beobachterklasse Beobachter {
  Konstruktor(Name, Betreff) {
    dieser.name = Name;
    dieses.Betreff = Betreff;
    dies.subject.addObserver(dies);
  }
  aktualisieren() {
    console.log(`${this.name}:${this.subject.state}`);
  }
}

4 Agenten erscheinen

Da die großen Vs mit ihrem Geschäft beschäftigt sind, brauchen sie Agenten, um die Verbindung zwischen Künstlern und Fans aufrechtzuerhalten.

Zu den Aufgaben eines Maklers gehören:

  • Um die Fans des großen V zu halten, wird der Agent eine Fanliste haben
  • Die neuen Werke des großen V werden dem Agenten übergeben, und der Agent ist dafür verantwortlich, die neuen Werke an die Fans in der Fanliste zu senden.

Abstrahieren Sie in eine Klasse wie folgt:

Klasse Manager {
  Konstruktor() {
    diese.fans = [];
    dies.funktioniert = [];
  }
  addFans(Fan) {
    dies.fans.push(Ventilator);
  }
  setWorks(Arbeit) {
    dies.funktioniert.push(arbeit);
    // Rufen Sie nach dem Hinzufügen der Arbeit die Aktualisierungsmethode this.workUpdate(); auf.
  }
  getWorks() {
    gib dies zurück.funktioniert;
  }
  arbeitsUpdate() {
    diese.fans.forEach((item) => item.update());
  }
}

Äh? Wo haben Sie diesen Code schon einmal gesehen?

Ja, es ist genau dasselbe wie die Star-Klasse in 2.2, außer dass der Klassenname geändert wurde.

Ist es also sinnvoll, dies zu tun?

Tatsächlich ist der Code genau derselbe, da wir in der Star-Klasse von 2.2 nur Funktionen geschrieben haben, die mit dem Veröffentlichen (also dem Veröffentlichen von Werken) und Abonnieren (also dem Verwalten einer Fanliste) zu tun haben; und die Star-Klasse selbst kann mehr als nur diese Aufgaben haben, beispielsweise das Erstellen von Inhalten.

Jetzt extrahieren wir die Veröffentlichungs- und Abonnementarbeit aus Star Klasse und übergeben sie Manager , der die volle Verantwortung übernimmt. Star Klasse muss die Arbeit erst nach Abschluss der Erstellung an Manager übergeben.

Andererseits interagieren Fan nicht mehr direkt mit Star . Sie interessieren sich nur dafür, ob sie die Werke erhalten können, und interagieren daher direkt mit Manager . Fan abonnieren den Manager (dieses Verhalten entspricht dem Hinzufügen von Fans zur vom Manager verwalteten Fanliste) und erhalten die gewünschten Werke vom Manager .

Der Code für Star und Fan lautet also wie folgt:

Klasse Stern {
  Konstruktor() {}
  // Erstellen create(manager) {
    // Übermitteln Sie die erstellte neue Arbeit an den Agenten manager.setWorks("neue Arbeit");
  }
}

Klasse Fan {
  Konstruktor(Name, Manager) {
    dieser.name = Name;
    dieser.manager = Manager;
    dies.manager.addFans(dies);
  }
  aktualisieren() {
    console.log(`${this.name}:${this.manager.getWorks()}`);
  }
}

5 Publish-Subscribe-Modell

Früher haben wir einen Broker für das Veröffentlichen und Abonnieren eingesetzt und keine direkte Interaktion zwischen Star und Fan zugelassen, wodurch der Effekt einer Entkopplung der beiden erreicht wurde.

Dies ist das Publish-Subscribe-Modell

Wir abstrahieren den Manager weiter in 4:

Stellen Sie sich „Fans“ als Subscriber vor; stellen Sie sich „große Vs“ als Herausgeber von Inhalten vor, die im Publish-Subscribe-Modell als Publisher bezeichnet werden; stellen Sie sich „Broker“ als Publish-Subscribe-Zentren (oder Mittelsmänner, Broker ) vor.

Der spezifische Code lautet wie folgt:

//Veröffentlichen und abonnieren Sie die Scheduling-Center-Klasse Broker {
  Konstruktor() {
    diese.abonnenten = [];
    // Stellt den Subjektstatus dar this.state = 0;
  }
  // Abonnierenabonnieren(Abonnent) {
    dies.subscribers.push(Abonnent);
  }
  // Den Designstatus ändern setState(state) {
    dieser.zustand = zustand;
    //Nachdem sich der Status geändert hat, veröffentlichen Sie dies.publish();
  }
  getState() {
    gib diesen Status zurück;
  }
  // Veröffentlichen publish() {
    this.subscribers.forEach((Abonnent) => Abonnent.update());
  }
}

// Publisher-Klasse Publisher {
  Konstruktor() {}
  changeState(Broker, Status) {
    broker.setState(status);
  }
}

Klasse Abonnent {
  Konstruktor(Name, Broker) {
    dieser.name = Name;
    dieser.Broker = Makler;
    dies.broker.subscribe(dies);
  }
  aktualisieren() {
    Konsole.log(`${this.name}:${this.broker.getState()}`);
  }
}

Lassen Sie es uns ausführen und die Wirkung beobachten:

// Ein Dispatch-Center erstellen const broker = new Broker()
// Einen Herausgeber erstellen const publisher = new Publisher()
// Einen Abonnenten erstellen const subscribe1 = new Subscriber('s1', broker)
const subscribe2 = neuer Abonnent('s2', Broker)
const subscribe3 = neuer Abonnent('s3', Broker)
// Der Herausgeber ändert den Status und benachrichtigt das Dispatch Center, das dann jeden Abonnenten benachrichtigt publisher.changeState(broker, 1)


6 Vergleich zwischen Observer-Modus und Publish-Subscribe-Modus

In Bezug auf die Anzahl der Rollen

  • Das Beobachtermuster hat nur zwei Rollen: Beobachter und beobachtet
  • Das Publish-Subscribe-Modell hat drei Rollen: Herausgeber, Abonnent und Mittelsmann (Publish-Subscribe-Center).

Vom Kopplungsgrad

  • Der Beobachtermodus befindet sich in einem lose gekoppelten Zustand, d. h. die beiden interagieren noch, können sich jedoch leicht gegenseitig erweitern, ohne sich gegenseitig zu beeinflussen.
  • Im Publish-Subscribe-Modell gibt es keine Kopplung zwischen Publishern und Abonnenten, wodurch der Effekt einer Entkopplung zwischen Objekten erreicht wird.

Aus der Perspektive der Absicht

  • Beide: Implementieren Sie eine Eins-zu-viele-Abhängigkeitsbeziehung zwischen Objekten. Wenn sich der Status eines Objekts ändert, werden alle davon abhängigen Objekte benachrichtigt und automatisch aktualisiert.

Dies ist das Ende dieses Artikels zum Schreiben eines Publish-Subscribe-Modells mit JS. Weitere relevante Inhalte zum Schreiben eines Publish-Subscribe-Modells mit JS finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • JavaScript-Entwurfsmuster: Detaillierte Erläuterung des Beobachtermodus und des Publish-Subscribe-Modus
  • Detaillierte Erläuterung der JavaScript-Implementierung und Verwendung des Publish/Subscribe-Modus
  • Analyse der Prinzipien und der Verwendung des JavaScript-Event-Publishing/Subscribing-Modells
  • Prinzip und Beispiel für die Implementierungsmethode des JavaScript-Entwurfsmusters „Observer-Modus“ (Veröffentlichungs- und Abonnementmodus)
  • Beispielerklärung des JS-Publish-Subscribe-Modus
  • Beispiel für ein Publish-Subscribe-Modell von Node.js
  • Ein einfaches Beispiel für das Publish/Subscribe-Muster in JavaScript

<<:  Eine kurze Analyse von Kubernetes-Controllern und -Labels

>>:  Hauptfunktionen von MySQL Innodb: Einfügepuffer

Artikel empfehlen

Detaillierte Erklärung des Rewrite-Moduls von Nginx

Das Umschreibmodul ist das Modul ngx_http_rewrite...

Wie stelle ich Tomcat als automatisch gestarteten Dienst ein? Der schnellste Weg

Stellen Sie Tomcat so ein, dass der Dienst automa...

Importieren von CSS-Dateien unter Verwendung von Beurteilungsbedingungen

Lösung 1: Verwenden Sie bedingten Import im HTML-...

Node.js erstellt ein einfaches Crawler-Case-Tutorial

Vorbereitung Zuerst müssen Sie nodejs herunterlad...

Ein Artikel bringt Ihnen bei, sauberen JavaScript-Code zu schreiben

Inhaltsverzeichnis 1. Variablen Verwenden Sie aus...

MySQL-Platzhalter (erweiterte SQL-Filterung)

Inhaltsverzeichnis Lassen Sie uns zunächst kurz P...

Der Implementierungsprozess der Linux-Prozessnetzwerkverkehrsstatistik

Vorwort Linux verfügt über entsprechende Open-Sou...

Analyse der Anweisungsausführungsreihenfolge von SQL und MySQL

Ich bin heute auf ein Problem gestoßen: Kann ich ...

JavaScript zum dynamischen Laden und Löschen von Tabellen

In diesem Artikel wird der spezifische JavaScript...

Fallbeispiel zur TypeScript-Schnittstellendefinition

Die Rolle der Schnittstelle: Schnittstelle, auf E...

Webdesign-Tutorial (5): Visuelles Webdesign

<br />Vorheriger Artikel: Webdesign-Tutorial...