個(gè)人感覺這個(gè)模式使用非常的廣泛膝擂。這是一個(gè)可以幫助你的對(duì)象知悉現(xiàn)狀亚斋,不會(huì)錯(cuò)過(guò)該對(duì)象感興趣的事。對(duì)象甚至在運(yùn)行時(shí)可決定是否要繼續(xù)被通知拂募。觀察者模式也是JDK中使用最多的模式之一庭猩。
**定義:**定義了對(duì)象之間的一對(duì)多依賴,這樣一來(lái)陈症,當(dāng)一個(gè)對(duì)象改變狀態(tài)時(shí)蔼水,它的所有依賴者都會(huì)收到通知并自動(dòng)更新。
觀察者模式是松耦合設(shè)計(jì)理念的一個(gè)很好的詮釋录肯。
使用場(chǎng)景:比如現(xiàn)在需要做一個(gè)氣象站監(jiān)測(cè)系統(tǒng)徙缴,要求系統(tǒng)可以隨時(shí)顯示最新的溫度,濕度,氣壓等信息于样,已知數(shù)據(jù)源為WeatherData對(duì)象疏叨,它會(huì)自動(dòng)從氣象站獲取數(shù)據(jù),現(xiàn)在的工作就是建立一個(gè)應(yīng)用穿剖,利用WeatherData對(duì)象取得數(shù)據(jù)更新布告板顯示最新的天氣信息蚤蔓;
由場(chǎng)景中可知道,變法的信息為天氣的狀態(tài)(溫度糊余,濕度秀又,氣壓),WeatherData對(duì)象負(fù)責(zé)收集這些信息贬芥,所以WeatherData對(duì)象可以作為一個(gè)狀態(tài)的發(fā)布者(既被觀察者)吐辙,布告板負(fù)責(zé)展示這些變化的信息,可以作為觀察者蘸劈。
所以首先聲明一個(gè)觀察者接口昏苏,所有的觀察者都必須實(shí)現(xiàn)這個(gè)借口用來(lái)接收被觀察者推送過(guò)來(lái)的信息,這個(gè)接口中只有一個(gè)update()方法威沫,用來(lái)更新天氣狀態(tài)信息贤惯。
public interface Observer {
public void update(float temp, float humidity, float pressure);
}
然后是被觀察者接口,被觀察者接口中可以添加棒掠,刪除觀察者孵构,并可以更新天氣狀態(tài)信息。
public interface Subject {
public void registerObserver(Observer o);
public void removeObserver(Observer o);
public void notifyObserver();
}
再增加一個(gè)布告板顯示接口烟很,用來(lái)顯示天氣狀態(tài)信息颈墅,之所以增加這個(gè)接口是考慮到以后可能會(huì)增加新的布告板。
public interface DisplayElement {
public void display();
}
下面是被觀察者的具體實(shí)現(xiàn)雾袱。
public class WeatherData implements Subject {
private List<Observer> observers;//用來(lái)存放觀察者
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
// TODO Auto-generated constructor stub
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
// TODO Auto-generated method stub
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
// TODO Auto-generated method stub
int i = observers.indexOf(o);
if (i >= 0) {
observers.remove(i);
}
}
@Override
public void notifyObserver() {//在這里把狀態(tài)告訴每一位觀察者
// TODO Auto-generated method stub
for (int i = 0; i < observers.size(); i++) {
Observer observer = (Observer) observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObserver();
}
/**測(cè)試數(shù)據(jù)**/
public void setMeasurements(float temperature, float humidity,
float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
下面是觀察者的具體實(shí)現(xiàn)精盅,觀察者需要實(shí)現(xiàn)Observer和DisplayElement兩個(gè)接口,一個(gè)用來(lái)接收新狀態(tài)谜酒,一個(gè)用來(lái)顯示狀態(tài)信息叹俏。
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {//傳遞個(gè)Subject對(duì)象是為了以后取消注冊(cè)方便
// TODO Auto-generated constructor stub
this.weatherData = weatherData;
weatherData.registerObserver(this);//注冊(cè)成為觀察者
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("Current conditios:" + temperature
+ "C degrees and " + humidity + "% humidity");
}
@Override
public void update(float temp, float humidity, float pressure) {
// TODO Auto-generated method stub
this.temperature = temp;
this.humidity = humidity;
display();
}
}
測(cè)試一下
public class WeatherStation {
public static void main(String[] args) {
// TODO Auto-generated method stub
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
}
}
打印結(jié)果:
Current conditios:80.0C degrees and 65.0% humidity
觀察者模式使用的OO原則:為交互對(duì)象之間的松耦合設(shè)計(jì)而努力!
其實(shí)在Android中用到觀察者模式的地方有很多僻族,常見的比如按鈕事件的監(jiān)聽粘驰,或者目前很流行的EventBus都是使用了觀察者模式。