仕事中に登場したので復習を兼ねて書きます。 デザインパターンの内容は結城浩『増補改訂版 Java言語で学ぶデザインパターン入門』を参照しています。
何がうれしいパターンなのか
観察対象(Subject*1)が変化したときに、観察者(Observer)に通知します。 状態変化に応じて、処理を記述できるようになります。
クラス図
デザインパターン本で頻出の、交換可能性を実現しています。
右側のObseverはインタフェースでも可。例ではインタフェースになっていました。
なお、Observerパターン自体にはSubjectに変化をもたらすものは登場しないので、例ではSubject内にexecuteとして実装されています。
import java.util.ArrayList; import java.util.Iterator; // Subject public abstract class NumberGenerator { private ArrayList observers = new ArrayList(); public void addObserver(Observer observer) { observers.add(observer); } public void deleteObserver(Observer observer) { observers.remove(observer); } public void notifyObservers() { Iterator it = observers.iterator(); while (it.hasNext()) { Observer o = (Observer)it.next(); o.update(this); } } public abstract int getNumber(); // getSubjectStatusにあたる public abstract void execute(); // デザインパターン範囲外 }
import java.util.Random; // ConcreteSubject public class RandomNumberGenerator extends NumberGenerator { private Random random = new Random(); private int number; public int getNumber() { return number; } public void execute() { for (int i = 0; i < 20; i++) { number = random.nextInt(50); notifyObservers(); } } }
java.util.ObserverインタフェースとObservableクラス
JDK1.0から、Observerパターンの一種がObserverインタフェースとObservableクラスによって備えられています。 しかし、書籍内では、subject役がObservableクラスを使う必要があるといった理由から、これらは使わずに自前で実装するのが良いとしています。
その主張は理解できますが、一方でその手法は原始的すぎるように感じ、より洗練された手法はないかと探してみることにしました。
Observerがdeprecatedになったことについて
Java9になってObserverやObservableがdeprecatedになったと書いてあります。
その理由について、Raviさんは以下の通り述べています。
- シリアライズできない
- ObservableがSerializableを実装していないため
- スレッドセーフでない
- イベント通知の順番が保証されず、別のスレッドでも起きうる
- イベントモデルがしょぼい
- 何かが変わったという通知は出せるが、何が変わったかという情報が得られない
また、ベストアンサーにあるように、それらはレガシーコードであるため、直すより取り潰したほうが早いという総合的な理由があります。
全体的にそりゃdeprecatedされるわという印象です。
代わりに何を使うかという話ですが、java.beans.PropertyChangeListenerが挙げられています。
まとめ
やろうとしていることは理解できますが、その手段としては、Observerパターンそのものでは古いという印象を持ちます。そこらへんの進化とかモバイルの関わり*2とかを調べたかったのですが進みきれませんでした。
デザインパターンシリーズ
その他記事
タイトルの形式をここと同じように『デザインパターン「○○」』にしました。全般的にデザパタ本をかなり丸々引用していて大丈夫か感は少しだけありますが、噛み砕かれているのとプラスアルファの記載もあって読みやすいです。