Javaオブザーバーモードjava.util.Observableとjava.util.Observerの理解


Part I
JDK 1.2の後、Javaは観察者モードのサポートインタフェースと実装クラスを提供した.
ここでインタフェースjava.util.Observerは、観察者を指定するために使用され、観察者はvoid update(Observable o,Object arg)メソッドを実装する必要があります.
一方java.util.Observableは、観察物(観察者、観察可能)を指定するために使用され、一連の方法が提供される.読者はこのインタフェースと実装クラスを簡単に使用して観察者モードを実現することができる.
 
Part II
JAva.util.Observerは単純な方法void update(Observable o,Object arg)しかありません
ここで、パラメータObservableはupdateメソッドをトリガするオブジェクトを指定し、Object argはupdateメソッドをトリガするときの追加パラメータを指定します.
デスクトップアプリケーションを開発した読者がいれば、これはイベント処理メカニズムと全く同じであり、Observable oはイベントソースと見なすことができることをよく知っているはずです.Object argはメッセージと見なすことができる.
 
Part III
あんなにたくさん言ったのに,やはり例を書きましょう.ここでは読者が雑誌を購読することを例に挙げます.
package com.gzmu.observer.observable;

import java.util.Observable;

public class Publisher extends Observable {

private String magazineName;


public String getMagazineName() {
return magazineName;
}

public void publish(String magazineName) {
this.magazineName = magazineName;
setChanged();
notifyObservers(this);
}

}
package com.gzmu.observer.observer;

import java.util.Observable;
import java.util.Observer;

import com.gzmu.observer.observable.Publisher;

public class Reader implements Observer {

@Override
public void update(Observable o, Object arg) {
Publisher p = (Publisher) o;
System.out.println(" " + p.getMagazineName());
}

}
package com.gzmu.observer.test;


import org.junit.Test;

import com.gzmu.observer.observable.Publisher;

public class TestCase {

@Test
public void register() {

Publisher publisher = new Publisher();
publisher.publish("Kent.Kuan ");

}

}

ここでは、出版社が雑誌を出版するとき、積極的に読者に知らせ、読者が雑誌を購読するのも、積極的にプッシュするモデルであることが明らかになった.
 
Part IV
ここで、notifyObservers()を呼び出すと、なぜ現在のオブジェクトthisに転送されるのでしょうか.このthis、私たちは読者にも使っていません.この問題はかつて私を悩ませて、前に私もどうして観察者が被観察対象の引用を手に入れるのか分かりませんが、次の例を見てみましょう.
まず、新しいクラスを参照します.
package com.gzmu.observer.observable;

import java.util.Observable;

public class TVStation extends Observable {

private String programmeName;

public void play(String programmeName) {
this.programmeName = programmeName;
setChanged();
notifyObservers(this);
}

public String getProgrammeName() {
return programmeName;
}

}

次にReaderとTestCaseを変更します.
package com.gzmu.observer.observer;

import java.util.Observable;
import java.util.Observer;

import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;

public class Reader implements Observer {

@Override
public void update(Observable o, Object arg) {
if (o instanceof Publisher) {
Publisher p = (Publisher) o;
System.out.println(" " + p.getMagazineName());
}
if (o instanceof TVStation) {
TVStation t = (TVStation) o;
System.out.println(" " + t.getProgrammeName());
}
}

}
package com.gzmu.observer.test;

import org.junit.Test;

import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;
import com.gzmu.observer.observer.Reader;

public class TestCase {

@Test
public void register() {

Reader reader = new Reader();

Publisher publisher = new Publisher();
publisher.addObserver(reader);

TVStation tvStation = new TVStation();
tvStation.addObserver(reader);

publisher.publish("Kent.Kwan ");
tvStation.play(" ");

}

}

最後に、同じ観察者は実際に異なる観察者に登録することができ、送られてきたOberverable oは実際に誰が送ったメッセージなのかを検証するために使用することができることを見ることができます.
このほか,メッセージを受け取った後,取り消し観察の作業を行うこともできる.
package com.gzmu.observer.observer;

import java.util.Observable;
import java.util.Observer;

import com.gzmu.observer.observable.Publisher;
import com.gzmu.observer.observable.TVStation;

public class Reader implements Observer {

@Override
public void update(Observable o, Object arg) {
if (o instanceof Publisher) {
Publisher p = (Publisher) o;
p.deleteObserver(this);
System.out.println(" " + p.getMagazineName());
}
if (o instanceof TVStation) {
TVStation t = (TVStation) o;
System.out.println(" " + t.getProgrammeName());
}
}

}

出版社オブジェクトの観察はdeleteObserver()メソッドで取り消すことができます.