總章目錄道伟,設(shè)計模式(一)基本介紹
一敲董、定義
觀察者模式:定義了對象之間的一對多依賴碳竟,這樣一來顽染,當(dāng)一個對象改變狀態(tài)時漾岳,他的所有依賴者都會受到通知并自動更新。
觀察者模式需要理解2個對象粉寞,觀察者和被觀察者:
舉個通用的例子:我們訂閱報紙蝗羊,那訂閱報紙的用戶則為觀察者,二報社則為被觀察者仁锯,而報社一旦發(fā)布新的報紙都會給訂閱人發(fā)報耀找。
觀察者模式的主要角色如下。
抽象主題(Subject):也叫抽象目標(biāo)類业崖,它提供了一個用于保存觀察者對象的聚集類和增加野芒、刪除觀察者對象的方法,以及通知所有觀察者的抽象方法双炕。
具體主題(Concrete Subject):也叫具體目標(biāo)類狞悲,它實(shí)現(xiàn)抽象目標(biāo)中的通知方法,當(dāng)具體主題的內(nèi)部狀態(tài)發(fā)生改變時妇斤,通知所有注冊過的觀察者對象摇锋。
抽象觀察者(Observer):它是一個抽象類或接口丹拯,它包含了一個更新自己的抽象方法,當(dāng)接到具體主題的更改通知時被調(diào)用荸恕。
具體觀察者(Concrete Observer):實(shí)現(xiàn)抽象觀察者中定義的抽象方法乖酬,以便在得到目標(biāo)的更改通知時更新自身的狀態(tài)
二、代碼示例
自己打造一個觀察者模式
思考下融求,為實(shí)時顯示氣象站獲取的氣象信息咬像,我們不采取觀察者設(shè)計模式,怎么去解決這個問題生宛。
Subject :
public interface Subject {
void addObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
Observer
public interface Observer {
/**
* 更新
*/
void update(float temp, float humidity, float pressure);
}
Concrete Subject:
public class WeatherData implements Subject {
List<Observer> observers;
float temp;
float humidity;
float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update(temp, humidity, pressure);
}
}
public void setWeather(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
notifyObservers();
}
}
Concrete Observer:
public class CurrentConditions implements Observer {
float temp;
float humidity;
float pressure;
@Override
public void update(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
showWeather();
}
private void showWeather() {
System.out.println("this="+this+"temp:" + temp + "humidity:" + humidity + "pressure:" + pressure);
}
}
測試輸出:
public class ObserverTest {
@Test
public void ObserverTest(){
WeatherData weatherData=new WeatherData();
CurrentConditions currentCondition1=new CurrentConditions();
CurrentConditions currentCondition2=new CurrentConditions();
weatherData.addObserver(currentCondition1);
weatherData.addObserver(currentCondition2);
weatherData.setWeather(10,20,30);
weatherData.setWeather(50,60,70);
weatherData.removeObserver(currentCondition1);
weatherData.setWeather(50,60,80);
}
}
打酉匕骸:
this=com.active_loser.Observer.CurrentConditions@1da51a35temp:10.0humidity:20.0pressure:30.0
this=com.active_loser.Observer.CurrentConditions@4b53f538temp:10.0humidity:20.0pressure:30.0
this=com.active_loser.Observer.CurrentConditions@1da51a35temp:50.0humidity:60.0pressure:70.0
this=com.active_loser.Observer.CurrentConditions@4b53f538temp:50.0humidity:60.0pressure:70.0
this=com.active_loser.Observer.CurrentConditions@4b53f538temp:50.0humidity:60.0pressure:80.0
通過上面打印的日志,可以看出陷舅,當(dāng)溫度改變后倒彰,所有訂閱的對象都會受到信息,當(dāng)某對象取消訂閱莱睁,將不會收到消息狸驳。
tip:當(dāng)然我們可以利用系統(tǒng)提供的觀察者Observer能夠夠方便的實(shí)現(xiàn)。
使用系統(tǒng)觀察者實(shí)現(xiàn)
通過setChanged()
和notifyObservers()
通知狀態(tài)改變
public class WeatherData extends Observable {
private float temp;
private float humidity;
private float pressure;
public float getTemp() {
return temp;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
public void setWeatherData(float temp, float humidity, float pressure) {
this.temp = temp;
this.humidity = humidity;
this.pressure = pressure;
//**標(biāo)識狀態(tài)已改表**
setChanged();
notifyObservers();
}
}
public class CurrentConditions implements Observer {
private float temp;
private float humidity;
private float pressure;
@Override
public void update(Observable o, Object arg) {
WeatherData weatherData = (WeatherData) arg;
System.out.println("this=" + this + "temp:" + temp + "humidity:" + humidity + "pressure:" + pressure);
}
}