观察者模式:
观察者模式使用的场景:
订阅者 + 出版者 = 观察者模式
观察者模式提供了一种对象设计,让观察者和主题之间松耦合。
在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖他的对象就会收到通知 ,并自动更新。
有两种对象,双方之间是一对多的关系,一方做出改变时需要通知其他方做改动。使用了观察者模式之后 需要被动做出变化的一方不需要一直查看主题方是否有变化。
使用时的关键之处:
主题提供方有一个专门用来保存观察者列表的list,观察者一方存在一个主题方用来将观察者注册到列表当中。
为了交互对象之间的松耦合设计而努力。
实例:
模拟一个气象站的例子 气象站在监测外界的温度 湿度 气压。当这三个要素发生变化时通知其他方发生了变化。
(由主题方维持一个监听方的list 提供注册 删除 通知的接口)
package com.wc.study.observer;
public interface Subject {
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyObservers();
}
具体的通知的方法:
package com.wc.study.observer;
public interface Observer {
/**
* 更新 温度 湿度 气压
* @param temperature
* @param humidity
* @param pressure
*/
void update(float temperature,float humidity, float pressure);
}
监听方用来展示结果的接口方法:
package com.wc.study.observer;
public interface DisplayElement {
void display();
}
主题方即本例中的气象站:
package com.wc.study.observer;
import java.util.ArrayList;
import java.util.List;
public class WeatherData implements Subject{
private float temperature;
private float humidity;
private float pressure;
private List<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
int index = observers.indexOf(observer);
if(index >= 0){
observers.remove(observer);
}
}
@Override
public void notifyObservers() {
for(Observer observer : observers){
observer.update(temperature, humidity, pressure);
}
}
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 com.wc.study.observer;
public class ConcreteObserver implements Observer,DisplayElement{
private float temperature;
private float humidity;
private float pressure;
private Subject subject;
public ConcreteObserver(Subject subject) {
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void display() {
System.out.println( "ConcreteObserver [temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure
+ "]");
}
@Override
public void update(float temperature, float humidity, float pressure) {
this.pressure = pressure;
this.temperature = temperature;
this.humidity = humidity;
display();
}
}
package com.wc.study.observer;
public class DmeoTest {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
weatherData.setHumidity(1.24f);
weatherData.setPressure(2.32f);
weatherData.setTemperature(23.4f);
ConcreteObserver observer1 = new ConcreteObserver(weatherData);
ConcreteObserver observer2 = new ConcreteObserver(weatherData);
ConcreteObserver observer3 = new ConcreteObserver(weatherData);
weatherData.notifyObservers();
// ConcreteObserver [temperature=23.4, humidity=1.24, pressure=2.32]
// ConcreteObserver [temperature=23.4, humidity=1.24, pressure=2.32]
// ConcreteObserver [temperature=23.4, humidity=1.24, pressure=2.32]
}
}
观察者模式: 全部都建立接口,主题的一方保留有观察者的列表,用于发生改变时通知。观察者一方留有主题的实现类,用于在创建时注册到列表当中。双方之间通过接口来相互调用,来达到松耦合的目的。
JDK实现的观察者模式:
观察者模式如此常用,在jdk中有具体的实现。
java对于观察者模式有自己内置的实现:Observer接口(有观察者一方来实现) Observable(主题的一方来继承)
实例:
package com.wc.study.jdk.observer;
import java.util.Observable;
//主题方
public class WeatherData extends Observable{
private float temperature;
private float humidity;
private float pressure;
public void setWeatherData(float temperature,float humidity,float pressure){
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
weatherDataChanged();
}
private void weatherDataChanged() {
setChanged();
notifyObservers();
}
public float getTemperature() {
return temperature;
}
public float getHumidity() {
return humidity;
}
public float getPressure() {
return pressure;
}
}
package com.wc.study.jdk.observer;
public interface DisplayElement {
void display();
}
package com.wc.study.jdk.observer;
import java.util.Observable;
import java.util.Observer;
public class ConcreteObserver implements Observer,DisplayElement{
private float temperature;
private float humidity;
private float pressure;
private Observable observable;
public ConcreteObserver(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData){
WeatherData weatherData = (WeatherData)o;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
this.pressure = weatherData.getPressure();
display();
}
}
@Override
public void display() {
// TODO Auto-generated method stub
System.out.println("ConcreteObserver [temperature=" + temperature + ", humidity=" + humidity + ", pressure=" + pressure
+ "]");
}
}
package com.wc.study.jdk.observer;
public class DemoTest {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
ConcreteObserver concreteObserver1 = new ConcreteObserver(weatherData);
ConcreteObserver concreteObserver2 = new ConcreteObserver(weatherData);
ConcreteObserver concreteObserver3 = new ConcreteObserver(weatherData);
weatherData.setWeatherData(1.02f, 2.32f, 23.3f);
// ConcreteObserver [temperature=1.02, humidity=2.32, pressure=23.3]
// ConcreteObserver [temperature=1.02, humidity=2.32, pressure=23.3]
// ConcreteObserver [temperature=1.02, humidity=2.32, pressure=23.3]
}
}
jdk自带的观察者模式存在缺点 : Observable 是一个类没有想用的接口 所以主题的一方需要继承但是java只提供单继承,我们不能提供自己的实现。