
Event Busは、“メッセージのバス(共通通路)” を中心に、複数のコンポーネントがイベントをやり取りする方式。
Pub-Subは、Event Bus の実装パターンのひとつです。
この連動する2つのパターンについて理解することで、イベント処理を効率的に設計できるようになります。
Event Bus / Pub-Sub の本質
このパターンは、部品同士をゆるく結合(Loosely Coupled)にする仕組みです。
“イベントを発行する側(Publisher)”が、“受け取る側(Subscriber)”を知らなくてよくなるという特徴があります。
システム全体を「通知の流れ」でつなぐ設計を理解しておきましょう。
特徴
Event Bus
・イベントは Bus に投げるだけ。
・Bus は購読者に一括で配信。
・発行側と受信側が完全に独立。
[Component A]
↓
(EventBus)
↓
[Component X]
[Component Y]
[Component Z]
Pub-Sub(Publish–Subscribe)
・Publisher(発行者) : イベントを Publish する
・Subscriber(購読者) : 必要なイベントを Subscribe する
丸ごと一方向なので、依存関係が最小化することができる。
Observer との違い
| 項目 |
Observer |
Pub-Sub(Event Bus) |
| 登録場所 |
Subject に直接登録 |
中央の EventBus に登録 |
| 双方向性 |
Subject ↔ Observer が直接関係 |
Publisher ⇄ Bus ⇄ Subscriber |
| 依存関係 |
Subject が Observer を知る |
完全非依存(疎結合) |
| 適用場面 |
オブジェクト同士の局所イベント |
システム全体の通知設計 |
ポイント
・Event Bus は“イベントを流す中央の通路”。
・Pub-Sub はそのモデルに基づくデザインパターン。
・Observer より疎結合で、システム全体の通知に強い。
・現代の多くのアーキテクチャ(Vue/React、Kafka、Flutter)は Pub-Sub をベースにしている。
サンプルコード1 : 超簡易 Event Bus
class EventBus {
constructor() {
this.subscribers = {};
}
subscribe(event, handler) {
if (!this.subscribers[event]) {
this.subscribers[event] = [];
}
this.subscribers[event].push(handler);
}
publish(event, data) {
if (this.subscribers[event]) {
this.subscribers[event].forEach(fn => fn(data));
}
}
}
// 使う側
const bus = new EventBus();
// Subscriber
bus.subscribe("user:created", (u) => {
console.log("ログ: ユーザー作成", u);
});
bus.subscribe("user:created", (u) => {
console.log("通知メール送信: ", u.name);
});
// Publisher
bus.publish("user:created", { id: 1, name: "Alice" });
ポイント解説
・Publisher は Subscriber を知らない
・Subscriber は Publisher を知らない
・この2つが"Pub-Sub"の最大の強み。
サンプルコード2 : DOMイベントをPub-Subとして利用
<div id="bus"></div>
<script>
// EventBusとして使うDOMノード
const bus = document.getElementById("bus");
// Subscriber(購読者)
bus.addEventListener("user:created", (e) => {
console.log("ログ処理:", e.detail);
});
bus.addEventListener("user:created", (e) => {
console.log("メール送信:", e.detail.name);
});
// Publisher(発行者)
function createUser(name) {
const user = { id: Date.now(), name };
// イベント発行
bus.dispatchEvent(new CustomEvent("user:created", {
detail: user
}));
}
// 実行
createUser("Alice");
</script>
ポイント解説
・bus という DOM ノードを EventBus として利用。
・user:created イベントを購読
・dispatchEvent() でイベントを発行
・すべての購読者が通知を受け取る
※DOM は「複数リスナー登録」「イベントバブリング」「カスタムイベント」を標準でサポートしているため、EventBus の役割に向いている。
よく使われる用途
・フロントエンド SPA のグローバルイベント。
・ゲームのイベント通知(HP減少、アイテム取得)。
・マイクロサービス間の非同期イベント配送(Kafka)。
・IoT 温度センサー → メッセージブローカー。
・UIコンポーネント間通信。
メリット
・コンポーネントが疎結合になる
・横断的な処理(ログ、通知、計測)が分離できる
・機能追加が容易(新しい Subscriber を追加するだけ)
・同期/非同期どちらでも使える
デメリット
・イベントの流れが見えにくい(デバッグが難しい)
・どこでイベントが消費されるか追いにくい
・設計が悪いと「何でもイベント化する地獄」になる
あとがき
イベントを独自で作成するEvent BusとPub-Subの書き方が理解できれば、結構手軽に自分でも使えるイメージが沸きますね。
サンプルコードのように、複数のイベントを一括実行することもできるし、他にも複雑なイベント構築ができるようになります。
Javascriptでのコード記述ですが、他の言語でも独自イベントとして使うこともできそうですね。
0 件のコメント:
コメントを投稿