bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. Pub/Sub パターンとは何か

Pub/Sub パターンとは何か

Mar 31, 2026 C# , .NET bucket-sort

システムが大きくなってくると、「あるクラスで起きた出来事を、別のクラスに知らせたい」という場面が増えてきます。直接メソッドを呼べばシンプルですが、呼び出し元が呼び出し先を直接知っているということは、両者が密接に結びついている(密結合)ということでもあります。

この密結合を避けるための設計パターンのひとつが Pub/Sub(パブリッシュ・サブスクライブ)パターン です。

Pub/Sub パターンとは

Pub/Sub は登場人物が3つあります。

役割 説明
Publisher(発行者) イベントやメッセージを送り出す側
Subscriber(購読者) メッセージを受け取って処理する側
Broker(仲介者) Publisher と Subscriber をつなぐ中間層

Publisher は「誰が受け取るか」を知りません。Subscriber は「誰が送ってきたか」を知りません。Broker がその橋渡しをすることで、両者は互いを意識せずに済みます。

Publisher → [Broker] → Subscriber A
                     → Subscriber B
                     → Subscriber C

C# での基本実装

まずシンプルな Pub/Sub の仕組みを自前で作ってみます。

// メッセージの型
public record OrderPlaced(int OrderId, string ProductName);

// Broker(メッセージバス)
public class MessageBus
{
    private readonly Dictionary<Type, List<Delegate>> _handlers = new();

    public void Subscribe<T>(Action<T> handler)
    {
        var type = typeof(T);
        if (!_handlers.ContainsKey(type))
            _handlers[type] = new List<Delegate>();

        _handlers[type].Add(handler);
    }

    public void Publish<T>(T message)
    {
        var type = typeof(T);
        if (!_handlers.TryGetValue(type, out var handlers)) return;

        foreach (var handler in handlers)
            ((Action<T>)handler)(message);
    }
}

Publisher 側はメッセージを Broker に投げるだけです。

var bus = new MessageBus();

// Subscriber A:注文ログを記録する
bus.Subscribe<OrderPlaced>(e =>
    Console.WriteLine($"[Log] 注文受付: {e.ProductName} (ID: {e.OrderId})")
);

// Subscriber B:メール通知を送る
bus.Subscribe<OrderPlaced>(e =>
    Console.WriteLine($"[Mail] {e.ProductName} のご注文ありがとうございます")
);

// Publisher:注文が確定したタイミングで発行
bus.Publish(new OrderPlaced(1001, "ノートPC"));

出力:

[Log] 注文受付: ノートPC (ID: 1001)
[Mail] ノートPC のご注文ありがとうございます

Publisher は Publish() を呼ぶだけで、ログとメール通知の両方が動きます。どちらの処理も Publisher は関知していません。

C# の event との違い

C# には event キーワードによる組み込みのイベント機構があります。Observer パターンに近い仕組みで、Pub/Sub と混同されることがあります。

比較項目 event Pub/Sub
仲介者 なし(直接登録) Broker が間に入る
結合度 Publisher が Subscriber の型を知る 互いに無関係
スコープ 同一プロセス内 プロセス・サービスをまたぐことも可能
用途 UI イベント、シンプルな通知 サービス間連携、非同期処理

event は手軽ですが、Publisher が Subscriber の存在を間接的に知っている形になります。Pub/Sub は Broker を挟むことでその依存を断ち切ります。

より実践的な構成

実務では次のような方向に発展します。

インターフェースで Subscriber を定義する

public interface IHandler<T>
{
    void Handle(T message);
}

public class OrderLogHandler : IHandler<OrderPlaced>
{
    public void Handle(OrderPlaced message)
        => Console.WriteLine($"[Log] 注文受付: {message.ProductName}");
}

クロージャーではなくクラスで Subscriber を表現することで、依存注入(DI)との相性が良くなります。

非同期対応

public interface IAsyncHandler<T>
{
    Task HandleAsync(T message, CancellationToken ct = default);
}

メール送信や外部 API 呼び出しなど、I/O を伴う処理は非同期ハンドラーに分けておくと扱いやすくなります。

外部サービスへの発展

Pub/Sub パターンはプロセス内だけでなく、サービス間の非同期通信にも広く使われています。

  • AWS SQS + SNS — SNS でメッセージを発行、SQS で受け取る
  • Azure Service Bus — トピック/サブスクリプション構成
  • RabbitMQ — Exchange と Queue による Broker 構成

アーキテクチャが大きくなるにつれ、Broker の役割は外部のメッセージングサービスが担うことになります。ただし基本の考え方は同じで、「Publisher と Subscriber を切り離す」という点は変わりません。

まとめ

Pub/Sub パターンのポイントを整理します。

  • Publisher はメッセージを投げるだけで、誰が受け取るかを知らない
  • Subscriber は何が発行したかを知らずにメッセージを処理する
  • Broker が両者を仲介することで、互いの依存を断ち切る
  • C# の event より疎結合で、スケールしやすい

小さなアプリでは event で十分ですが、処理が増えて「どこで何をしているか」が分散してきたタイミングで Pub/Sub を検討する価値が出てきます。

C# .NET デザインパターン
← PHP/Laravel で値の状態を判定するヘルパ関数まとめ [C#] delegate と event の仕組みを整理する →

Related Posts

  • [C#] delegate と event の仕組みを整理する Apr 1, 2026
  • [C#] Interlockedの使い方 Mar 27, 2026
  • [C#] ImmutableHashSet<T>の使い方 Mar 26, 2026
  • [C#] HashSet<T>の使い方 Mar 25, 2026

Table of Contents

  • Pub/Sub パターンとは
  • C# での基本実装
  • C# の event との違い
  • より実践的な構成
    • インターフェースで Subscriber を定義する
    • 非同期対応
  • 外部サービスへの発展
  • まとめ

Recent Posts

  • Laravel の Event / Listener で Pub/Sub を実装する Apr 2, 2026
  • [C#] delegate と event の仕組みを整理する Apr 1, 2026
  • Pub/Sub パターンとは何か Mar 31, 2026
  • PHP/Laravel で値の状態を判定するヘルパ関数まとめ Mar 30, 2026
  • Filament の dehydrated メソッドとは何か Mar 29, 2026

Categories

  • AWS27
  • C#22
  • .NET20
  • Laravel16
  • Linux12
  • Apache8
  • MySQL8
  • PHP8
  • DynamoDB6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • セキュリティ3
  • .NET Framework1
  • Aurora1
  • Filament1
  • Git1
  • SQS1

Tags

  • AWS
  • C#
  • .NET
  • Laravel
  • PHP
  • MySQL
  • セキュリティ
  • Linux
  • Apache
  • Code Snippet
  • DynamoDB
  • NoSQL
  • PHP-FPM
  • RDS
  • DoS
  • Nginx
  • Windows
  • WordPress
  • パフォーマンス
  • 監視
  • Amazon Linux 2023
  • CMS
  • Docker
  • Ipset
  • Iptables
  • OPCache
  • Webサーバー
  • 認可
  • Aurora
  • Blade
Powered by Hugo & Explore Theme.