java相關技術(partner4java專欄)希望對您的學習有所幫助
阿新 • • 發佈:2019-01-24
觀察者模式:定義了物件之間的一對多的依賴,這樣一來,當一個物件改變狀態時,他的所有者就會立刻接到通知並自動更新。
觀察者模式定義了一系列物件之間的一對多關係。
當一個物件改變狀態,當其他依賴者都會收到通知。
實現觀察者模式的方法不止一種,但是以包含Subject與Observer介面的類的設計最為常見。
這和一對多的關係有何關聯?
利用觀察者模式,主題是具有狀態的物件,並且可以控制這些狀態。也就是說,有“一個”具有狀態的主題。
另一方面,觀察者使用這些狀態,雖然這些狀態並不屬於他們。有許多的觀察者,依賴主題來告訴他們狀態
何時改變了。這就產生了一個關係:“一個”主題對“多個”觀察者的關係。
期間的依賴是如何產生的?
因為主題是真正擁有資料的人,觀察者是主題的依賴者,在資料變化更新,這樣比起讓許多物件控制一份資料來,可以得到更乾淨OO設計。
觀察者模式定義了一系列物件之間的一對多關係。
當一個物件改變狀態,當其他依賴者都會收到通知。
實現觀察者模式的方法不止一種,但是以包含Subject與Observer介面的類的設計最為常見。
這和一對多的關係有何關聯?
利用觀察者模式,主題是具有狀態的物件,並且可以控制這些狀態。也就是說,有“一個”具有狀態的主題。
另一方面,觀察者使用這些狀態,雖然這些狀態並不屬於他們。有許多的觀察者,依賴主題來告訴他們狀態
何時改變了。這就產生了一個關係:“一個”主題對“多個”觀察者的關係。
期間的依賴是如何產生的?
因為主題是真正擁有資料的人,觀察者是主題的依賴者,在資料變化更新,這樣比起讓許多物件控制一份資料來,可以得到更乾淨OO設計。
設計原則:為了互動物件之間的鬆耦合設計而努力
Demo:
業務場景:
建立一個應用,有三種佈告板,分別顯示目前的狀況、氣象統計及簡單的預報。
當WeatherObject物件獲得最新的測量資料時,三種佈告板必須實時更新。
這是一個可以擴充套件的氣象站,其他開發人員可以寫出自己的氣象佈告板,並插入到應用中。
package cn.partner4java.weather; /** * 主業務類(管理觀察員、並負責呼叫觀察員) * @author partner4java * */ public interface Subject { /** * 註冊觀察員 * @param observer 觀察員 */ public void registerObserver(Observer observer); /** * 刪除觀察員 * @param observer 觀察員 */ public void removeObserver(Observer observer); /** * 通知所有的觀察者 */ public void notifyObserver(); }
package cn.partner4java.weather;
/**
* 佈告板
* (如:目前狀況佈告板、統計佈告板、預測佈告板)
* @author partner4java
*
*/
public interface DisplayElement {
/**
* 佈告呼叫方法
*/
public void display();
}
package cn.partner4java.weather; /** * 觀察員(氣象發生改變時,被呼叫的物件) * @author partner4java * */ public interface Observer { /** * 所有的觀察者都必須實現這個方法,以實現觀察者介面 * @param temperature 溫度 * @param humidity 溼度 * @param pressure 氣壓 */ public void update(float temperature,float humidity,float pressure); }
package cn.partner4java.weather.impl;
import java.util.ArrayList;
import java.util.List;
import cn.partner4java.weather.Observer;
import cn.partner4java.weather.Subject;
/**
* 氣象資料獲取類
* 主業務類(管理觀察員、並負責呼叫觀察員)
* 實現主體介面
* @author partner4java
*
*/
public class WeatherData implements Subject {
/** 觀察者列表 */
private List<Observer> observers;
/** 溫度 */
private float temperature;
/** 溼度 */
private float humidity;
/** 氣壓 */
private float pressure;
public WeatherData(){
observers = new ArrayList<Observer>();
}
@Override
public void notifyObserver() {
for(int i=0;i<observers.size();i++){
Observer observer = observers.get(i);
observer.update(temperature, humidity, pressure);
}
}
@Override
public void registerObserver(Observer observer) {
int i = observers.indexOf(observer);
if(i == -1){
observers.add(observer);
}
}
@Override
public void removeObserver(Observer observer) {
int i = observers.indexOf(observer);
if(i >= 0){
observers.remove(i);
}
}
/**
* 當從氣象站得到更新觀測值時,我們通知觀察者
*/
public void measurementsChanged(){
notifyObserver();
}
/**
* 設定氣象改變資料
* @param temperature 溫度
* @param humidity 溼度
* @param pressure 氣壓
*/
public void setMeasurements(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
public List<Observer> getObservers() {
return observers;
}
public void setObservers(List<Observer> observers) {
this.observers = observers;
}
public float getTemperature() {
return temperature;
}
public void setTemperature(float temperature) {
this.temperature = temperature;
}
public float getHumidity() {
return humidity;
}
public void setHumidity(float humidity) {
this.humidity = humidity;
}
public float getPressure() {
return pressure;
}
public void setPressure(float pressure) {
this.pressure = pressure;
}
}
package cn.partner4java.weather.impl;
import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;
import cn.partner4java.weather.Subject;
/**
* 目前狀況佈告板
* @author partner4java
*
*/
public class CurrentConditionsDisplay implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData){
this.weatherData = weatherData;
this.weatherData.registerObserver(this);
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
@Override
public void display() {
System.out.println("CurrentConditionsDisplay: temperature-" + temperature +
" humidity-" + humidity);
}
}
package cn.partner4java.weather.impl;
import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;
/**
* 未來天氣預告版
* @author partner4java
*
*/
public class ForecastDisplay implements DisplayElement, Observer {
/** 當前氣壓 */
private float currentPressure = 29.92f;
/** 最後一次氣壓 */
private float lastPressure;
private WeatherData weatherData;
public ForecastDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.print("Forecast: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
} else if (currentPressure == lastPressure) {
System.out.println("More of the same");
} else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
}
@Override
public void update(float temperature, float humidity, float pressure) {
lastPressure = currentPressure;
currentPressure = pressure;
display();
}
}
package cn.partner4java.weather.impl;
import cn.partner4java.weather.DisplayElement;
import cn.partner4java.weather.Observer;
/**
* 統計狀態佈告
* @author partner4java
*
*/
public class StatisticsDisplay implements DisplayElement, Observer {
/** 最高溫度 */
private float maxTemp = 0.0f;
/** 最低溫度 */
private float minTemp = 200;
/** 記錄總溫度 */
private float tempSum = 0.0f;
/** 溫度讀取次數 */
private int countReadings;
private WeatherData weatherData;
public StatisticsDisplay(WeatherData weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("StatisticsDisplay: maxTemp-" +
maxTemp + " minTemp-" + minTemp + " averageTemp-" +
tempSum/countReadings);
}
@Override
public void update(float temperature, float humidity, float pressure) {
tempSum += temperature;
countReadings++;
if(temperature < minTemp){
minTemp = temperature;
}else if(temperature > maxTemp){
maxTemp = temperature;
}
display();
}
}
package cn.partner4java.weather.test;
import cn.partner4java.weather.impl.CurrentConditionsDisplay;
import cn.partner4java.weather.impl.ForecastDisplay;
import cn.partner4java.weather.impl.StatisticsDisplay;
import cn.partner4java.weather.impl.WeatherData;
/**
* 氣象站測試(啟動氣象站)
* @author partner4java
*
*/
public class WeatherStation {
/**
* @param args
*/
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionsDisplay currentConditionsDisplay = new CurrentConditionsDisplay(weatherData);
StatisticsDisplay statisticsDisplay = new StatisticsDisplay(weatherData);
ForecastDisplay forecastDisplay = new ForecastDisplay(weatherData);
weatherData.setMeasurements(80, 234, 20.4f);
weatherData.setMeasurements(56, 232, 20.4f);
weatherData.setMeasurements(34, 123, 20.4f);
}
}