免責
いきなり免責というのもアレですが、この記事の真偽は一切保証を致しかねます。
正直、かなり怪しいと思いますので、少なくとも情報収集されている方は、この記事はスキップされたほうが無難かと思われます。
(私のアカウントに書いてあることはもともと正しさの保証は一切できないのですが^^;)
目的
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 というクラスがある |
うーん、ややこしい・・・
コメント