unityマンへの道 その2:observeのpush型

前回はobservableの使い方を勉強した。
今回はアレの改良版を作る。引き続き下記記事を参照している。

qiita.com

前回のMainメソッドを改めて見る。

class Program
{
    static void Main(string args)
    {
        //監視する寿司レーンを作った
        var subject = new SushiLaneSubject();
        //寿司を食べたい人を二人作成する。
        //(Subjectを監視する人を二人作る。ここではSubject=寿司レーンなので、「寿司レーン監視するマン」が二人作成された。
        var observer1 = new SushiObserver() { Subject = subject };
        var observer2 = new SushiObserver() { Subject = subject };

        //寿司レーンに寿司を食べたい二人を着席させる。
        //-!監視するマンを作成するだけではダメで、監視対象側にそいつらを渡してやる必要がある。
        subject.Subscribe(observer1);

        subject.Subscribe(observer2);

        //寿司レーンにネタが現れる
        subject.Neta = "まぐろ";
        //ネタが来た通知を出す。
        subject.NotifyObservers();
    }
}

まだギリギリ分かるな…

さて、このコードでは通知を出す前にネタの種類を定義している。
また、NotifyObserverという「寿司レーン内の監視役にネタが来たことを通知するメソッド」を通知した後、監視役(observer1,2)がthis.Subject.Netaを自分で参照しに行かねばならない。

簡単に言うと

寿司レーン「来たよ!」
監視役「来たか!何が来た?」
寿司レーン「まぐろだよ!」
監視役「やったー!」

という流れになっている。寿司レーンが「まぐろきたよ!」と初めから言ったほうが簡潔だ。
また、監視役は寿司レーンのインスタンスがNetaという変数を内部に保持していることを事前に知っておく必要がある。クラス間の結合が強い状態だ。これはよろしくない。

ということで、以前勉強した「ジェネリック」を使ってインターフェースを編集する。具体的には以下のように。

//監視する人
public interface IObserver<TValue>
{
void OnNotified(TValue value);
}

//監視対象
public interface ISubject<TValue> {
void NotifyObservers(TValue value);
void Subscribe(IObserver<TValue> observer);
void Unsubscrive(IObserver<TValue> observer);
}

 

このインターフェースを継承する監視役と監視対象は、各メソッドが引数を持てるように作り変える。
寿司レーンはNotifyObserversを実行する時点で引数としてネタを渡す。
すると、監視役は直接ネタの種類を受け取ることができるので、わざわざ別インスタンスまで値を参照しに行かなくてよくなる。

class Program
{
    static void Main(string args)
    {
        //監視する寿司レーンを作った
        var subject = new SushiLaneSubject();
        //寿司を食べたい人を二人作成する。
        //(Subjectを監視する人を二人作る。ここではSubject=寿司レーンなので、「寿司レーン監視するマン」が二人作成された。
        var observer1 = new SushiObserver() { Subject = subject };
        var observer2 = new SushiObserver() { Subject = subject };

        //寿司レーンに寿司を食べたい二人を着席させる。
        //-!監視するマンを作成するだけではダメで、監視対象側にそいつらを渡してやる必要がある。
        subject.Subscribe(observer1);
        subject.Subscribe(observer2);

        //寿司レーンにネタが現れる
        //ネタが来た通知を出す。
        subject.NotifyObservers("まぐろ");
    }
}

 

つまり、こう。

繰り返し書くが、コードを全部書くと元の記事の人に悪い気がするのでここまで。復習するときは記事を見に行こう。

 

前回のものは、監視役が別インスタンスに値を自分から取りに行くので「pull型」、今回のものは、監視役は別インスタンスから値を押し付けられるので「push型」と呼ばれるらしい。

一般的にインスタンス、クラス間の結合を弱くすることがコーディングの原則なので、push型を使うようにしていこう。

引用元の記事はあと少し続くので、明日はそれを勉強する。