觀察者模式理解和編碼都比較簡單,通常包括以下步驟:
1. 設計觀察者接口類;
2. 觀察者類實現該接口;
3. 設計被觀察者抽象類,該類中提供一些方法,如:添加觀察者對象,刪除觀察者對象,把事件通知給各個觀察者對象;
4. 設計被觀察者類,繼承被觀察者抽象類,在該類中,可以根據需要在該類中,可以定義方法:被觀察者是否發生變化
以上四步,即完成了觀察者模式的設計。下面代碼分類進行描述以上步驟:
package Observer;
import java.util.Enumeration;
import java.util.Vector;
abstract public class Subject {
?private Vector observersVector = new java.util.Vector();
?
?public void attach(Observer observer){
??observersVector.addElement(observer);
??System.out.println("Attached an observer.");
?}
?
?public void detach(Observer observer){
??observersVector.removeElement(observer);
?}
?
?public void notifyObservers(){
??java.util.Enumeration enumeration = observers();
??while(enumeration.hasMoreElements()){
???System.out.println("Before notifying");
???((Observer)enumeration.nextElement()).update();
??}
?}
?
?public Enumeration observers(){
??return ((java.util.Vector)observersVector.clone()).elements();
?}
}
package Observer;
public class ConcreteSubject extends Subject{
?private String state;
?
?public void change(String newState){
??state = newState;
??this.notifyObservers();
?}
}
package Observer;
public interface Observer {
?void update();
}
package Observer;
public class ConcreteObserver implements Observer{
?
?public void update(){
??System.out.println("I am notified.");
?}
}
package Observer;
public class Client {
?private static ConcreteSubject subject;
?private static Observer observer1;
?private static Observer observer2;
?
?public static void main(String[] args){
??subject = new ConcreteSubject();
??observer1 = new ConcreteObserver();
??observer2 = new ConcreteObserver();
??
??subject.attach(observer1);
??subject.attach(observer2);
??
??subject.change("new state");
?}
}
運行結果是:
Attached an observer.
Attached an observer.
Before notifying
I am notified.
Before notifying
I am notified.
在java中提供了Observerable類和Observer接口來實現觀察者模式
- extends Object
public class Observable
此類表示模型視圖范例中的 observable 對象,或者說“數據”。可將其子類化,表示應用程序想要觀察的對象(即被觀察者)。
一個 observable 對象可以有一個或多個觀察者。觀察者可以是實現了 Observer 接口的任意對象。一個 observable 實例改變后,調用 Observable
的 notifyObservers
方法的應用程序會通過調用觀察者的 update
方法來通知觀察者該實例發生了改變。
未指定發送通知的順序。Observable 類中所提供的默認實現將按照其注冊的重要性順序來通知 Observers,但是子類可能改變此順序,從而使用非固定順序在單獨的線程上發送通知,或者也可能保證其子類遵從其所選擇的順序。
注意,此通知機制與線程無關,并且與 Object 類的 wait 和 notify 機制完全獨立。
新創建一個 observable 對象時,其觀察者集合是空的。當且僅當 equals 方法為兩個觀察者返回 true 時,才認為它們是相同的。
public interface Observer
一個可在觀察者要得到 observable 對象更改通知時可實現 Observer
接口的類。?
?給個用java機制來實現觀察者模式的例子
在java機制中Observable類相當于抽象主題角色,我們定義具體主題角色來繼承該類
Observer 接口相當于抽象觀察者角色,我們定義具體觀察者角色來實現該接口
所以這兩個抽象角色我們不用編寫了 只需編寫兩個具體角色
//----具體觀察對象角色
package Observer.javaObserver;
import java.util.Observable;
public class Product extends Observable{
?private String name;
?private float price;
?
?public String getName(){
??return name;
?}
?
?public void setName(String name){
??this.name = name;
??// 設置變化點
??setChanged();
??notifyObservers(name);//通知觀察者
?}
?public float getPrice() {
??return price;
?}
?public void setPrice(float price) {
??this.price = price;
??//設置變化點
??setChanged();
??notifyObservers(new Float(price));
?}
?
?public void saveToDb(){
??System.out.println("saveToDb");
?}
}
//------------ 兩個具體觀察者角色
package Observer.javaObserver;
import java.util.Observable;
import java.util.Observer;
public class NameObserver implements Observer {
?private String name = null;
?
?public void update(Observable obj, Object arg){
??if(arg instanceof String){
???name = (String)arg;
???System.out.println("NameObserver:name changed to " + name);
??}
?}
}
package Observer.javaObserver;
import java.util.Observable;
import java.util.Observer;
public class PriceObserver implements Observer{
?private float price=0;
?
?public void update(Observable obj, Object arg){
??if(arg instanceof Float){
???price = ((Float)arg).floatValue();
???System.out.println("PriceObserver: price change to" + price);
??}
?}
}
//----測試程序
package Observer.javaObserver;
import java.util.Observer;
public class Test {
?public static void main(String[] args){
??Product product = new Product();
??Observer nameObs = new NameObserver();
??Observer priceObs = new PriceObserver();
??
??product.addObserver(nameObs);
??product.addObserver(priceObs);
??
??product.setName("apple");
??product.setPrice(9.22f);
??
??product.setName("Apple");
??product.setPrice(9.88f);
??}
}
//---運行結果
NameObserver:name changed to apple
PriceObserver: price change to9.22
NameObserver:name changed to Apple
PriceObserver: price change to9.88