JS でパブリッシュ サブスクライブ モデルを作成する

JS でパブリッシュ サブスクライブ モデルを作成する

パブリッシュ・サブスクライブ・モデルとは何ですか?手書きで書けますか?オブザーバーパターンとは違うのでしょうか? ...

1. シーン紹介

次のようなシナリオを見てみましょう。

Nami

ナミはとても才能があり、多才です。現在、彼女は曲を書くこととビデオを撮影することという2つのスキルを持っています。

彼女はこれらの作品をプラットフォームに投稿する予定です。彼女をフォローしているファンはこれらのコンテンツを受け取ることができます

現在、彼にはルフィ、ゾロ、サンジの3人のファンがいる。

ナミさんが作品を発表するたびに、3人のファンのアカウントに寄せられたメッセージが更新されていきます。

では、コードで表現してみましょう。

定数ルフィ = {
  更新: 関数 (曲、ビデオ) {
    console.log(曲、ビデオ);
  },
};
定数ゾロ = {
  更新: 関数 (曲、ビデオ) {
    console.log(曲、ビデオ);
  },
};
定数サンジ = {
  更新: 関数 (曲、ビデオ) {
    console.log(曲、ビデオ);
  },
};

定数ナミ = {
  // このメソッドはナミの作業が更新されるたびに呼び出されます workUpdate: function () {
    // 作品を取得します const songs = this.getSongs();
    const ビデオ = this.getVideos();

    //アカウント更新 luffy.update(songs, videos);
    zoro.update(曲、ビデオ);
    sanji.update(曲、ビデオ);
  },
  getSongs: 関数 () {
    "mp3"を返します。
  },
  getVideos: 関数 () {
    "mp4"を返します。
  },
};

ここで問題が起こります

  • Nami別のファンでRobinを獲得した場合、 robinオブジェクトを追加し、 workUpdateメソッドを変更する必要があります。
  • Nami小説を書くという新しいスキルがある場合、パラメータが 1 つ増えたため、各ファン オブジェクトのworkUpdate関数とupdateメソッドの両方を変更する必要があります。

何か問題が見つかりましたか?

ファン オブジェクトとインフルエンサー オブジェクト間の結合が高すぎるため、それぞれを独立してスケーリングすることが困難になります。

2 コードの最適化

2.1 ファンを増やす問題を解決する

まず最初の問題を解決して、ファンを追加するときにworkUpdateメソッドを変更する必要がないようにしましょう。

まず、「大きな V」を Star クラスに抽象化し、配列fansを使用してファン リストを保存し、ファンを追加するためのメソッドaddFans追加します。

クラス スター {
  コンストラクタ() {
    this.fans = [];
  }
  ファンを追加します(ファン) {
    this.fans.push(ファン)
  }
  作業更新() {
    const songs = this.getSongs();
    const ビデオ = this.getVideos();
    this.fans.forEach((item) => item.update(songs, videos));
  }
  getSongs() {
    "MP3"を返します。
  }
  動画を取得する() {
    "MP4"を返します。
  }
}

次に、「ファン」を Fan クラスに抽象化します。ファン オブジェクトを作成するときに、「big V」オブジェクトを渡し、big V のaddFansメソッドを呼び出してファン リストに追加します。

クラスファン{
  コンストラクタ(名前、星) {
    this.name = 名前
    this.star = 星
    this.star.addFans(これ)
  }
  更新(曲、ビデオ) {
    console.log(曲、ビデオ);
  }
}


ファンを追加するためにコードを変更する必要がなくなりました

const nami = 新しい Star()
const luffy = new Fan("luffy", nami);
const zoro = new Fan("zoro", nami);
const sanji = new Fan("sanji", nami);
const robin = new Fan("robin", nami);
nami.workUpdate()

2.2 作品追加の問題を解決する

big V の作業を保存するためのworks配列を追加し、それにgetsetメソッドを追加します。

クラス スター {
  コンストラクタ() {
    this.fans = [];
    これは動作します = [];
  }
  ファンを追加します(ファン) {
    this.fans.push(ファン);
  }
  setWorks(作業) {
    this.works.push(作業);
    // 作業を追加した後、更新メソッドを呼び出します this.workUpdate();
  }
  getWorks() {
    this.works を返します。
  }
  作業更新() {
    this.fans.forEach((item) => item.update());
  }
}


それに応じて Fan クラスを変更します。

クラスファン{
  コンストラクタ(名前、星) {
    this.name = 名前
    this.star = 星
    this.star.addFans(これ)
  }
  アップデート() {
    console.log(`${this.name}:${this.star.getWorks()}`)
  }
}


これで、大きな V では、コードを変更して動作を追加する必要がなくなりました。

const nami = new Star();
nami.setWorks('song')
nami.setWorks('ビデオ')
nami.setWorks('小説')
const luffy = new Fan("luffy", nami);
const zoro = new Fan("zoro", nami);
const sanji = new Fan("sanji", nami);
nami.workUpdate();

3 オブザーバーパターン

ご覧のとおり、上記の例では、 namiオブジェクトと複数のファン オブジェクトの間に 1 対多の依存関係があります。nami オブジェクトに作業の更新があると、彼女をフォローしているすべてのnamiオブジェクトに通知が送信されます。

実際、これは観察者モードです

オブザーバー パターン:オブジェクト間の 1 対多の依存関係を定義します。オブジェクトの状態が変化すると、それに依存するすべてのオブジェクトに通知され、自動的に更新されます。

2.2 ではコードをさらに抽象化します。

「ファン」はObserverとみなされ、「大きなV」は観察の対象、つまりSubjectとみなされます。

Subjectオブザーバー リストobserverList (元々は fans 配列) を維持します。 Subjectの状態が変化すると (original workUpdate)、notify (original workUpdate ) メソッドを呼び出してすべてのオブザーバーに通知され、それぞれのupdateメソッドが実行されます。

具体的なコードは次のとおりです。

//オブザーバー: サブジェクトクラスSubject {
  コンストラクタ() {
    this.observerList = [];
    // サブジェクトの状態を表します this.state = 0;
  }
  オブザーバーを追加します(オブザーバー) {
    this.observerList.push(オブザーバー);
  }
  // テーマの状態を変更する setState(state) {
    this.state = 状態;
    //状態が変化したら、すべてのオブザーバーに通知します this.notify();
  }
  状態を取得する() {
    this.state を返します。
  }
  通知() {
    this.observerList.forEach((オブザーバー) => observer.update());
  }
}

//オブザーバークラスオブザーバー{
  コンストラクタ(名前, 件名) {
    this.name = 名前;
    this.subject = 件名;
    this.subject.addObserver(これ);
  }
  アップデート() {
    console.log(`${this.name}:${this.subject.state}`);
  }
}

4人のエージェントが登場

大手Vはビジネスで忙しいため、アーティストとファンのつながりを維持するためのエージェントが必要です。

ブローカーの職務には以下が含まれます。

  • ビッグVのファンを維持するために、エージェントはファンリストを持っている
  • ビッグVの新作はエージェントに引き渡され、エージェントはファンリスト内のファンに新作を届ける役割を担います。

次のようにクラスに抽象化します。

クラスマネージャー{
  コンストラクタ() {
    this.fans = [];
    これは動作します = [];
  }
  ファンを追加します(ファン) {
    this.fans.push(ファン);
  }
  setWorks(作業) {
    this.works.push(作業);
    // 作業を追加した後、更新メソッドを呼び出します this.workUpdate();
  }
  getWorks() {
    this.works を返します。
  }
  作業更新() {
    this.fans.forEach((item) => item.update());
  }
}

えっと?このコードを以前どこで見たことがありますか?

はい、クラス名が変更されていることを除けば、2.2 の Star クラスとまったく同じです。

それで、これをやる意味はあるのでしょうか?

実際、コードはまったく同じです。2.2 の Star クラスでは、公開 (つまり、作品の公開) と購読 (つまり、ファンのリストの維持) に関連する関数のみを記述しており、Star クラス自体には、コンテンツの作成など、この作業以外にも多くの機能がある可能性があります。

ここでStarクラスからパブリッシュとサブスクリプションの作業を抽出し、 Managerに完全に責任を持たせます。 Starクラスは、作成が完了したら作業をManagerに引き渡すだけで済みます。

一方、 Fan Starと直接やりとりすることはなくなりました。ファンが関心があるのは作品を受け取れるかどうかだけなので、 Managerと直接やりとりすることになります。 Fan Managerを購読し (この動作は、 Managerが管理するファン リストにファンを追加することと同じです)、 Managerから希望する作品を取得します。

したがって、Star と Fan のコードは次のようになります。

クラス スター {
  コンストラクタ() {}
  // 作成 create(manager) {
    // 作成した新しい作業をエージェントに送信します。 manager.setWorks("new work");
  }
}

クラスファン{
  コンストラクタ(名前、マネージャ) {
    this.name = 名前;
    this.manager = マネージャー;
    this.manager.addFans(これ);
  }
  アップデート() {
    console.log(`${this.name}:${this.manager.getWorks()}`);
  }
}

5 パブリッシュ・サブスクライブモデル

以前は、パブリッシュとサブスクライブを担当するブローカーを使用し、 StarFan直接やり取りできないようにすることで、2 つを切り離す効果を実現していました。

これはパブリッシュ・サブスクライブモデルです

4 ではマネージャーをさらに抽象化します。

「ファン」をSubscriberと考えてください。「ビッグ V」をコンテンツの発行者(パブリッシャー/サブスクライブ モデルではPublisherと呼ばれます)と考えてください。「ブローカー」をパブリッシュ/サブスクライブ センター(または仲介人、 Broker )と考えてください。

具体的なコードは次のとおりです。

//パブリッシュおよびサブスクライブ スケジューリング センター クラス Broker {
  コンストラクタ() {
    this.subscribers = [];
    // サブジェクトの状態を表します this.state = 0;
  }
  // 購読購読(購読者) {
    this.subscribers.push(サブスクライバー);
  }
  // テーマの状態を変更する setState(state) {
    this.state = 状態;
    //状態が変化したら、公開します。this.publish();
  }
  状態を取得する() {
    this.state を返します。
  }
  // 公開 publish() {
    this.subscribers.forEach((subscriber) => subscriber.update());
  }
}

// パブリッシャークラス Publisher {
  コンストラクタ() {}
  状態の変更(ブローカー、状態) {
    ブローカーの状態を設定します。
  }
}

クラス サブスクライバー {
  コンストラクタ(名前、ブローカー) {
    this.name = 名前;
    this.broker = ブローカー;
    this.broker.subscribe(これを);
  }
  アップデート() {
    console.log(`${this.name}:${this.broker.getState()}`);
  }
}

実行して効果を確認してみましょう:

// ディスパッチセンターを作成する const broker = new Broker()
// パブリッシャーを作成する constpublisher = new Publisher()
// サブスクライバーを作成する const subscribe1 = new Subscriber('s1', broker)
const subscribe2 = 新しいサブスクライバー('s2', ブローカー)
const subscribe3 = 新しいサブスクライバー('s3'、ブローカー)
// パブリッシャーは状態を変更し、ディスパッチ センターに通知します。ディスパッチ センターは各サブスクライバーに通知します。publisher.changeState(broker, 1)


6 オブザーバーモードとパブリッシュ・サブスクライブモードの比較

役割の数に関して

  • オブザーバーパターンには、オブザーバーとオブザーブドの2つの役割しかありません。
  • パブリッシュ・サブスクライブモデルには、パブリッシャー、サブスクライバー、仲介者(パブリッシュ・サブスクライブセンター)の3つの役割があります。

結合度から

  • オブザーバー モードは疎結合状態です。つまり、2 つは依然として相互作用しますが、互いに影響を与えることなく、相互に拡張することが容易です。
  • パブリッシュ サブスクライブ モデルでは、パブリッシャーとサブスクライバー間の結合がないため、オブジェクト間の分離の効果が得られます。

意図の観点から

  • 両方: オブジェクト間の 1 対多の依存関係を実装します。オブジェクトの状態が変化すると、それに依存するすべてのオブジェクトに通知され、自動的に更新されます。

JS でパブリッシュ サブスクライブ モデルを作成する方法についての記事はこれで終わりです。JS でパブリッシュ サブスクライブ モデルを作成する方法についての関連コンテンツについては、123WORDPRESS.COM の以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • JavaScript デザイン パターン: オブザーバー モードとパブリッシュ サブスクライブ モードの詳細な説明
  • JavaScript の実装とパブリッシュ/サブスクライブ モードの使用に関する詳細な説明
  • JavaScript イベント公開/購読モデルの原理と使用法の分析
  • JavaScript デザインパターン オブザーバーモード(パブリッシュ アンド サブスクライブモード)の原理と実装方法の例
  • js パブリッシュ・サブスクライブモードの例の説明
  • Node.js パブリッシュ・サブスクライブモデルの例
  • JavaScript でのパブリッシュ/サブスクライブパターンの簡単な例

<<:  Kubernetes コントローラーとラベルの簡単な分析

>>:  MySQL Innodbの主な機能挿入バッファ

推薦する

Vueの7つの値転送メソッドの詳細な説明

1. 父から息子へ子コンポーネントにpropsフィールドを定義し、その型は配列です (フィールド値の...

MySQL における exists、in、any の基本的な使い方

【1】存在するループを使用して外部テーブルを 1 つずつクエリし、各クエリの存在する条件ステートメン...

独自の YUM リポジトリを作成する手順

簡単に言うと、ウェアハウスとして使用される仮想マシンの IP は 192.168.149.129 で...

Linuxシステムにおける仮想デバイスファイルのさまざまな実用的な使用法の詳細な説明

みなさんこんにちは。私は梁旭です。ご存知のとおり、Linux ではデバイス ファイルも含めすべてがフ...

MySQL で行を列に変換したり、列を行に変換したりする詳細な例

mysql 行から列へ、列から行へ難しい文章ではないので、詳しく説明はしません。文章を読むときは、一...

Docker イメージのダウンロードが遅すぎる場合の解決策

Docker イメージのダウンロードが停止したり、遅すぎたりするネットでいろいろな方法を検索しました...

HTMLの基礎を詳しく解説(第2部)

1. リストリスト ulコンテナーには、一貫した構造とスタイルを持つテキストまたはグラフの形式が読...

Webpack プロジェクトでローダー プラグインをデバッグする方法

最近、webpackの使い方を学んでいたときに、webpack-replace-loaderの設定正...

仮想マシン VMware に Kali Linux をインストールする最新の超詳細なグラフィック チュートリアル

目次1. システムイメージファイルをダウンロードする2. 新しい仮想マシンを作成する3. Kali ...

MySQL で遅い SQL 文を見つける方法

MySQL で遅い SQL ステートメントを見つけるにはどうすればよいでしょうか?これは、多くの人を...

ソフトウェア 404 と 404 エラーとは何か、またそれらの違いは何ですか

まず、404 とソフト 404 とは何でしょうか? 404: 簡単に言えば、ユーザーが存在しないペー...

IE8 と Chrome でテーブルの幅を修正する方法

IE8 や Chrome で上記の設定を使用すると、画面の最大幅に合わせて表示が統一され、各列の幅は...

JavaScript イベントバブリング、イベントキャプチャ、イベント委任の詳細な説明

1. イベントバブリング: JavaScript イベント伝播のプロセスでは、要素でイベントがトリガ...

Kubernetes (k8s) 入門

Kubernetes は面白そうだったので(ギリシャ人なら名前に問題があると思うでしょうが)、ずっと...

vue_drf は SMS 認証コードを実装します

目次1. 需要1. 需要2. SDKパラメータ設定1. ディレクトリ構造3. コードの実装1. バッ...