免責
いきなり免責というのもアレですが、この記事の真偽は一切保証を致しかねます。
正直、かなり怪しいと思いますので、少なくとも情報収集されている方は、この記事はスキップされたほうが無難かと思われます。
(私のアカウントに書いてあることはもともと正しさの保証は一切できないのですが^^;)
目的
GoFのデザインパターンの中で有名度トップ5には絶対入っているであろう「Observer パターン」ですが、そこに出てくる登場人物が個人的にはとってもわかりにくい!
やっていることは「何かが起きた時に、その何かを他の誰かへ通知する」というデザインパターンの中でもシンプルなほうなので、実装時にもよく使うんですが。
しかし、登場人物というか、その登場人物の呼び方がシチュエーションによってコロコロ変わるのが本当に厄介です。
例えば、GoF では Subject/Observer だったり、別名 Pub/Sub 方式と呼ばれ Publisher/Subscriber だったり、Rx では IObservable/IObserver だったり・・・
ということで、個人的な備忘録として GoF でいう Obesrver は、 Pub/Sub 方式では?Rx では?というのを書いてみます。
それぞれの比較
GoF の Observer パターン
まず、GoF のデザインパターンで出てくるやつです。
「イベントを発行する人(= 発火元)」が Subject です。
「イベントを受信して処理する人」が、 Observer です。
上記の場合だと、シーケンス的には以下の感じになるでしょうか。
- あらかじめ、
Subjectは、Observerを登録しておく
(Subject#AddObserverの実行) Subjectにて何かイベントが発生した場合は、Observerへ通知する
(Subject#NotifyObserversの実行 ⇒ 内部ではObserver#Updateの実行)ObserverはUpdateを受けて、何かしらのイベント処理を行う
言ってしまえば、Subject は観察対象、Observer は観察者ですよね。そのまんまですが。
Pub/Sub パターン
次に、GoF の Observer パターンはよく「別名 Pub/Sub パターンとも呼ばれる」と言われていますが、 Pub/Sub パターンでは Observer パターンの登場人物がどのように割り当てられるのか整理してみます。
と、その前にそもそも、「Observer パターン = Pub/Sub パターン」というのは厳密に言うと誤りらしいです。
基本的な考え方は同じなんですが、 Pub/Sub パターンでは、いわゆる Publisher と Subscriber の間に「Broker」なるものが介在します。この辺はこちらに詳しく書かれているので、省略します。
が、ここでは無理やり登場人物をあてはめます。
「イベントを発行する人(= 発行者)」が Publisher です。
「イベントを受信して処理する人(=購読者)」が、 Subscriber です。
「イベントをとりまとめる人(=仲介人)」が、 Broker です。とりまとめると言うとあやふやなので、「メッセージを受け取ると、購読登録者へ配達する人」みたいな感じでしょうか。
シーケンス的には以下になると思います。
- あらかじめ
Subscriberは購読したいイベントのtopic(イベント名みたいなもの)を、Brokerに登録しておく
(Broker#Subscribeの実行) Publisherは何らかのイベントが発生した場合は、topicと共にBrokerへ通知する
(Broker#Publishの実行)Brokerは、あらかじめ登録されているSubscriberに対してイベントを通知するSubscriberはイベントを受け取ると、何かしらのイベント処理を行う
つまり、Pub/Sub パターンを Observer パターンに当てはめた場合、以下のような対応になります。
イベント発生側:Publisher = Subject 、 イベント受信側:Subscriber = Observer
※ ただし、やはり Observer パターンとは異なり、Publisher と Subscriber は基本的に依存関係にありません(つまり疎結合)。Publisher は自身が通知したイベントがどの Subscriber が購読しているか知りませんし、 Subscriber もイベントの発信元がどの Publisher なのかを知りません。
Rx (Reactive Extensions)
はっきりいって、 Rx はまったくの初心者というか勉強中の身なので偉そうなことは書けませんが、今自分が把握していること(というか理解したつもりでいること)を書きます。
もうまんまなのですが、 GoF の Observer パターンでいうと、IObserveable = Subject で、 IObserver = Observer ですね。(この時点で、なぜ名前を統一しないのか!GoF の定義をそのまま使ってくれ!と思っちゃいます1)
そして、さらに恨み節ですが、「IObservable が Subscribe メソッドを持つ」というのが個人的にわかりにくい。こんがらがる原因は Observer パターンが Pub/Sub パターンと関連しているという前提認識があるからなのだと思いますが、本来 IObserver が購読者であるはずなのに、 IObservable が Subscribe するというのが混乱の元になってます。2
また、もっとやっかいなことに Rx では Subject という「 IObservable と IObserver の両方を実装した、一人二役する」クラスがいます。
「おーい、IObservable = Subject やなかったんかーい」って、もうこの段階でパニックです。
まとめ
ということで、 Rx やるうえで、以下のことを覚えておきます。
| パターン名 | イベントの発行元(= 発行者)の呼び方 | イベントの受信先(= 購読者)の呼び方 | 備考 |
|---|---|---|---|
| Observer パターン | Subject | Observer | |
| Pub/Sub パターン | Publisher | Subscriber | |
| Rx | IObservable | IObserver | ※ただし、IObservable と IObserver の両方を実装する Subject というクラスがある |
うーん、ややこしい・・・


コメント