觀察者模式是對(duì)象的行為模式,顧名思義,即存在觀察者和被觀察者。?觀察者模式可以讓多個(gè)觀察者同時(shí)監(jiān)聽同一個(gè)被觀察對(duì)象,當(dāng)被觀察對(duì)象發(fā)生變化時(shí),并通知所有觀察者,使各個(gè)觀察者能作出相應(yīng)的響應(yīng)。適當(dāng)?shù)剡\(yùn)用觀察者模式,能提高自身代碼的設(shè)計(jì)水平。
觀察者模式理解和編碼都比較簡(jiǎn)單,通常包括以下步驟:
1. 設(shè)計(jì)觀察者接口類;
2. 觀察者類實(shí)現(xiàn)該接口;
3. 設(shè)計(jì)被觀察者抽象類,該類中提供一些方法,如:添加觀察者對(duì)象,刪除觀察者對(duì)象,把事件通知給各個(gè)觀察者對(duì)象;
4. 設(shè)計(jì)被觀察者類,繼承被觀察者抽象類,在該類中,可以根據(jù)需要在該類中,可以定義方法:被觀察者是否發(fā)生變化
以上四步,即完成了觀察者模式的設(shè)計(jì)。下面代碼分類進(jìn)行描述以上步驟:
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");
?}
}
運(yùn)行結(jié)果是:
Attached an observer.
Attached an observer.
Before notifying
I am notified.
Before notifying
I am notified.
在java中提供了Observerable類和Observer接口來實(shí)現(xiàn)觀察者模式
public class Observable
- extends Object
此類表示模型視圖范例中的 observable 對(duì)象,或者說“數(shù)據(jù)”。可將其子類化,表示應(yīng)用程序想要觀察的對(duì)象(即被觀察者)。
一個(gè) observable 對(duì)象可以有一個(gè)或多個(gè)觀察者。觀察者可以是實(shí)現(xiàn)了 Observer 接口的任意對(duì)象。一個(gè) observable 實(shí)例改變后,調(diào)用 Observable
的 notifyObservers
方法的應(yīng)用程序會(huì)通過調(diào)用觀察者的 update
方法來通知觀察者該實(shí)例發(fā)生了改變。
未指定發(fā)送通知的順序。Observable 類中所提供的默認(rèn)實(shí)現(xiàn)將按照其注冊(cè)的重要性順序來通知 Observers,但是子類可能改變此順序,從而使用非固定順序在單獨(dú)的線程上發(fā)送通知,或者也可能保證其子類遵從其所選擇的順序。
注意,此通知機(jī)制與線程無關(guān),并且與 Object 類的 wait 和 notify 機(jī)制完全獨(dú)立。
新創(chuàng)建一個(gè) observable 對(duì)象時(shí),其觀察者集合是空的。當(dāng)且僅當(dāng) equals 方法為兩個(gè)觀察者返回 true 時(shí),才認(rèn)為它們是相同的。
public interface Observer
一個(gè)可在觀察者要得到 observable 對(duì)象更改通知時(shí)可實(shí)現(xiàn) Observer
接口的類。?
?給個(gè)用java機(jī)制來實(shí)現(xiàn)觀察者模式的例子
在java機(jī)制中Observable類相當(dāng)于抽象主題角色,我們定義具體主題角色來繼承該類
Observer 接口相當(dāng)于抽象觀察者角色,我們定義具體觀察者角色來實(shí)現(xiàn)該接口
所以這兩個(gè)抽象角色我們不用編寫了 只需編寫兩個(gè)具體角色
//----具體觀察對(duì)象角色
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;
??// 設(shè)置變化點(diǎn)
??setChanged();
??notifyObservers(name);//通知觀察者
?}
?public float getPrice() {
??return price;
?}
?public void setPrice(float price) {
??this.price = price;
??//設(shè)置變化點(diǎn)
??setChanged();
??notifyObservers(new Float(price));
?}
?
?public void saveToDb(){
??System.out.println("saveToDb");
?}
}
//------------ 兩個(gè)具體觀察者角色
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);
??}
?}
}
//----測(cè)試程序
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);
??}
}
//---運(yùn)行結(jié)果
NameObserver:name changed to apple
PriceObserver: price change to9.22
NameObserver:name changed to Apple
PriceObserver: price change to9.88