デザインパターン「Observerパターン」

By | 2017/01/31

機能

1対多関連に対する応答がしやすい
SubjectとObserverが疎結合なので変更に対して影響し合わない

実装例

// オブサーバーを登録して、更新があったら通知する
interface Subject{
  // observerを追加する
  public void add(Observer o);
  // observerを削除する
  public void delete(Observer o);
  // 持っているobserverに通知する
  public void notify();

  private ArrayList _observers;
}
// サブジェクトに通知してもらえるように共通のインターフェースを持ったオブジェクトを作る
interface Observer(){
  // 通知を受け取って更新する
  public void update();
}

class ConcreteSubject implements Subject{
  public void add(Observer o){
    _observer.add(o);
  }
  public void delete(Observer o){
    _observer.delete(o);
  }
  public void notify(){
    foreach(var o in _observer){
      o.update();
    }
  }
}

検討

どういったところで使えそうか。
例えばゲームに出てくる敵キャラなどは一定の処理を毎フレーム行うのでObserverとして扱える。Observerの更新処理ではキャラがいなければ適当に歩いて、キャラが近くにいたら攻撃とかにする。この敵の行動とかはStrategyパターンでも使って行動を変えたらいいかも。

UIなんかも使えそうと思ったけど、よくある表示物を考えると、「ただの表示用」と「主人公のHPゲージ」とか「ミニマップ」とかを同じ扱いとして更新はしにくそう。あくまでObserverは同じような種類のものでないと扱いにくい。

 

そう考えるとこのパターンはかなり限定した同じ種類のものに対して一括して扱うのに適している。この「限定した同じ種類」の見極めを間違うと無理な設計になってコードが汚くなりそう。最初は慎重に確実に同じ種類のものをこのパターンで使用していくのがいいと思う。

Subjectはインターフェイスではなく抽象クラスで良い気もする。追加、削除、通知はおそらく基本的にはやることは同じだ。ただ通知などは通知する順番などに意味のある場合もある。追加も特定の条件を満たしたものを追加、みたいにちょっと複雑になることもあるかもしれない。そう考えるとインターフェイスで実装しておいた方が無難か。

 

基本的には同じ種類のものをたくさん同じ処理する場合にこのパターンを思い浮かべれば良さそうだ。


コメントを残す

メールアドレスが公開されることはありません。