定義
觀察者模式定義了對(duì)象之間的一對(duì)多依賴先舷,這樣當(dāng)一個(gè)對(duì)象(稱為主題)改變狀態(tài)時(shí)坡疼,它的所有依賴者(稱為觀察者)都會(huì)收到通知并自動(dòng)更新镀钓。
類圖
觀察者模式類圖
其中所涉及到的對(duì)象有:
- 抽象主題(Subject)接口:將觀察者對(duì)象引用存放在一個(gè)集合里(例如ArrayList)进栽,封裝了對(duì)觀察者的一些行為方法雷滋,可以進(jìn)行觀察者的注冊(cè)(添加對(duì)象)、刪除以及喚醒(向觀察者送出通知)臼勉。
- 具體主題(ConcreteSubject):掌握一些數(shù)據(jù)邻吭,實(shí)現(xiàn)了主題接口中對(duì)觀察者的操作方法。
- 抽象觀察者(Observer)接口:為所有具體的觀察者定義了一個(gè)接口宴霸,在接到主題通知時(shí)囱晴,更新自己。
- 具體觀察者(ConcreteObserver):包含了主題對(duì)象的引用瓢谢,當(dāng)主題對(duì)象改變時(shí)畸写,利用update()方法更新自己。
實(shí)例
建設(shè)一個(gè)氣象站氓扛,其中包括氣象觀測站以及天氣布告板枯芬。氣象觀測站有天氣的各項(xiàng)參數(shù),它將參數(shù)推送給布告板讓其顯示天氣參數(shù)采郎。
代碼:
public interface Subject{//抽象主題類
public abstract void registerObserver(Observer observer);
public abstract void removeObserver(Observer observer);
public abstract void notifyObservers();
}
public class WeatherData implements Subject{//具體主題類
ArrayList<Observer> observers;
private float temerature;
private float humidity;
private float pressure;
public WeatherData(){
observers=new ArrayList<Observer>();
}
public void registerObserver(Observer observer){//添加觀察者
observers.add(observer);
}
public void removeObserver(Observer observer){//刪除觀察者
observers.remove(observer);
}
public void notifyObservers(){//向觀察者推送更新
for(int i=0;i<observers.size();i++){
Observer o=observers.get(i);
o.update(temperature,humidity,pressure);
}
}
public void measurementsChanged(){//客戶端調(diào)用該方法觀測更新
notifyObservers();
}
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
measurementsChanged()
}
public interface Observer{//觀察者接口
abstract void update(float temperature,float humidity,float pressure);
}
public class Display implements Observer{//具體觀察者類
private float temperature;
private float humidity;
private float pressure;
Subject subject;
public Display(Subject subject){
this.subject=subject;
}
public void update(float temp,float humidity,float pressure){
this.temperature=temp;
this.humidity=humidity;
this.pressure=pressure;
display();
}
public void display(){
//實(shí)現(xiàn)顯示
}
}
public class Client{//客戶端
public static void main(String[] args){
WeatherData weatherData=new WeatherData();//創(chuàng)建主題對(duì)象
Display display=new Display(weatherData);//創(chuàng)建觀察者對(duì)象千所,并與對(duì)應(yīng)主題關(guān)聯(lián)
weatherData.setMeasurements(80,65,30f);//設(shè)置更新數(shù)據(jù),此時(shí)已經(jīng)向觀察者推送了更新同時(shí)觀察者收到了更新蒜埋。
}
}
擴(kuò)展
- 可以在主題中加入標(biāo)記主題狀態(tài)是否更改的變量淫痰,以便更好地給觀察者推送更新
- 以上介紹的觀察者模式中只有主題將自己所有的數(shù)據(jù)都推送給觀察者,不管觀察者是否需要整份『诮纾可以加入觀察者自己“拉”數(shù)據(jù)的模式,只獲取其有用的數(shù)據(jù)皂林。即在主題中加入返回?cái)?shù)據(jù)的方法
- java JDK中提供了觀察者模式的接口,其為java.util包中的Observable(主題)類和Observer接口蚯撩,該模式提供了“推”和“拉”數(shù)據(jù)兩種方法础倍。
- 觀察者模式實(shí)現(xiàn)了主題和對(duì)象之間的松耦合,即它們彼此可以交互胎挎,但是不清楚彼此的細(xì)節(jié)沟启。