本文主要介紹的是Java觀察者模式的理解與基本實現的Demo;在學習設計模式的時候,需要考慮的是爲什麼會出現這種模式,爲什麼我們需要使用這種模式,類比到我們生活中一個熟悉的場景理解意義,落實到代碼上確實的理解到什麼是該模式,以及該模式的代碼實現上與普通實現的區別在哪,爲什麼使用了該模式之後項目的開發在遇到改變或者其他情況的時候會比較容易修改和更新;以上是我在學習與使用設計模式的時候一些感想;
本文中demo來自於HeadFirst設計模式,特此聲明;
1、觀察者模式初識
2、觀察者模式運用
3、觀察者模式實現
1、觀察者模式初識
首先是兩個例子:
1、情景一:在學校的時候,咱們老師要通知某件事情的時候會走進教室給大家說該通知(notifyAll),但是,有些同學並不需要遵循該通知,所以老師就請該同學暫時不用聽(remove),當然如果隔壁班的老師有事兒,這個時候我們就會請那個班的班長來我們班(add),一起接受該通知,回頭,該班長就會將該通知傳遞給他們班的同學(該班長在這個時候就有事觀察者有事被觀察者);
2、情景二:如果需要寫一個天氣通知的程序,我們可以動態的從天氣站獲取數據,但是我們通知的時候假設有三個展板,每個展板依次是天氣預告、天氣統計、目前狀況,並且我們可能隨時移除或者添加新的具有混合信息的展板,在這個時候,觀察者模式就起到了很大作用了;
2、觀察者模式運用
情景:還是一個情景:報紙與雜誌的訂閱:
報社出版報紙,當我們想報社訂閱報紙(訂閱就是add)的時候只要有新的報紙出版就會給我們寄送過來(通知就是notify),當我們不想再閱讀報紙的時候只需要取消訂閱即可(取消訂閱就是remove),在有新的報紙出版的時候(也就是所謂的信息改變)就不會有通知;出版者(報社) + 訂閱者 = 觀察者模式
Subject + Observer = 觀察者模式
3、觀察者模式實現(以1種的情景二作爲例子)
Subject.java
public interface Subject {
// 註冊觀察者
public void registerObserver(Observer o);
// 移除觀察者
public void removeObserver(Observer o);
// 通知所有觀察者
public void notifyObserver();
}
Observer.java
public interface Observer {
// 觀察者使用方法獲取主題數據
public void update(float temperature , float humidity , float pressure);
}
WeatherData.java(天氣信息)
import java.util.ArrayList;
public class WeatherData implements Subject {
// 存儲當前的所有觀察者
// 使用鏈表方便添加與移除的操作
private ArrayList<Observer> observers;
// 溫度,溼度,氣壓數據
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<Observer>();
}
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
// 一定要先進行判斷這個觀察着是否在鏈表中
if (i >= 0) {
observers.remove(o);
}
}
@Override
public void notifyObserver() {
for (Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
// 當發生改變的時候通知所有的觀察者
public void measurementsChanged() {
// 發送改變調用該方法
notifyObserver();
}
// 設置信息,當信息發送變化進行通知操作
public void setMeasurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
measurementsChanged();
}
}
DisplayElement.java(展示)
public interface DisplayElement {
// 佈告板需要顯示的時候調用此方法
public void display();
}
CurrentCondiDisplay.java (其中一塊天氣信息的展示)
public class CurrentCondiDisplay implements Observer , DisplayElement {
private float temperature;
private float humidity;
// 提供信息的主題
@SuppressWarnings("unused")
private Subject weatherData;
public CurrentCondiDisplay(Subject weatherData) {
this.weatherData = weatherData;
// 當生成該對象的時候自動添加到可以觀察的鏈表中
weatherData.registerObserver(this);
}
@Override
public void display() {
System.out.println("CurrentCondiDisplay [temperature=" + temperature
+ ", humidity=" + humidity + "]");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
WeatherStation.java(天氣信息展示的測試)
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
// 註冊觀察者
@SuppressWarnings("unused")
CurrentCondiDisplay currentCondiDisplay = new CurrentCondiDisplay(weatherData);
weatherData.setMeasurements(80, 65.0f, 30.4f);
}
}
類圖: