观察者模式又称为发布/订阅(Publish/Subscribe)模式,因此我们可以用报纸期刊的订阅来形象的说明:
报社方负责出版报纸.
你订阅了该报社的报纸,那么只要报社发布了新报纸,就会通知你,或发到你手上.
如果你不想再读报纸,可以取消订阅,这样,报社发布了新报纸就不会再通知你.
理解其实以上的概念,就可以理解观察者模式,观察者模式中有主题(Subject)和观察者(Observer),分别对应报社和订阅用户(你).观察者模式定义了对象之间的一对多的依赖关系,这样,当"一"的一方状态发生变化时,它所依赖的"多"的一方都会收到通知并且自动更新.如图:
image.png image.png
实现
主题接口
package com.ghgcn.model.observer1;
public interface Obserable {
/**
* 注册
* @param observer
*/
public void registerObserver(Observer observer);
/**
* 取消订阅
* @param observer
*/
public void removeObserver(Observer observer);
/**
* 通知所有观察者
*/
public void notifyObserver ();
}
观察者接口
package com.ghgcn.model.observer1;
/**
* 观察都接口
* @author Administrator
*
*/
public interface Observer {
/**
* 更新方法
* @param temperature
* @param humidity
* @param pressure
*/
void update(float temperature, float humidity, float pressure);
}
显示接口
package com.ghgcn.model.observer1;
public interface DispatyElement {
public void display();
}
主题实现
package com.ghgcn.model.observer1;
import java.util.ArrayList;
import java.util.List;
import com.sun.tracing.dtrace.ProviderAttributes;
public class WeatherDate implements Obserable {
/**
* 用来存放观察者
*/
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherDate(){
observers = new ArrayList<Observer>();
}
public void registerObserver(Observer observer) {
observers.add(observer);
}
public void removeObserver(Observer observer) {
int indexOf =observers.indexOf(observer);
if(indexOf>=0){
observers.remove(indexOf);
}
}
public void notifyObserver() {
for( int i = 0 ; i <observers.size() ; i++){
Observer o=observers.get(i);
o.update(this.temperature,this.humidity,this.pressure);
}
}
/**
* 改变,调用notifyObserver
*/
public void measurementsChanged(){
notifyObserver();
}
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 com.ghgcn.model.observer1;
public class CurrentConditionsDisplay implements Observer, DispatyElement {
private Obserable weatherDate;
private float temperature;
private float humidity;
private float pressure;
public CurrentConditionsDisplay(Obserable weatherDate){
this.weatherDate=weatherDate;
weatherDate.registerObserver(this);
}
public void display() {
System.out.println("CurrentConditionsDisplay :\n temperature: "+this.temperature+" \n humidity:"+this.humidity+"\n pressure:"+this.pressure);
}
public void update(float temperature, float humidity, float pressure) {
this.temperature=temperature;
this.humidity=humidity;
this.pressure=pressure;
display();
}
}
测试
package com.ghgcn.model.observer1;
public class Test1 {
public static void main(String[] args) {
WeatherDate weatherDate = new WeatherDate();
CurrentConditionsDisplay c1 = new CurrentConditionsDisplay(weatherDate);
//CurrentConditionsDisplay c2 = new CurrentConditionsDisplay(weatherDate);
//CurrentConditionsDisplay c3 = new CurrentConditionsDisplay(weatherDate);
weatherDate.setMeasurements(32.6f, 65.3f, 30.4f);
weatherDate.setMeasurements(20.6f, 33.1f, 67.8f);
weatherDate.setMeasurements(18.6f, 45.2f, 88.9f);
weatherDate.setMeasurements(-20.6f, 35.6f, 93.0f);
}
}
结果
CurrentConditionsDisplay :
temperature: 32.6
humidity:65.3
pressure:30.4
CurrentConditionsDisplay :
temperature: 20.6
humidity:33.1
pressure:67.8
CurrentConditionsDisplay :
temperature: 18.6
humidity:45.2
pressure:88.9
CurrentConditionsDisplay :
temperature: -20.6
humidity:35.6
pressure:93.0
JAVA内置的观察者
主题 是一个类不是一个接口
public class Observable {
//标题位, 为true中通知观察都
private boolean changed = false;
//存放所有的订阅者
private Vector<Observer> obs;
/** Construct an Observable with zero Observers. */
public Observable() {
//构造方法初始化容器
obs = new Vector<>();
}
/**
添加观察者,也就是注册 这里加了同步锁
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
移除观察者
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
通知所有观察者发生变化了
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
通知所有观察者发生变化了
*/
public void notifyObservers(Object arg) {
/*
缓冲容器
*/
Object[] arrLocal;
synchronized (this) {
/*
判断标题位是否为true,false就不向下执行通知,为 true时才通知
*/
if (!changed)
return;
//初始化缓冲容器,所有操作都在这个容器上实现
arrLocal = obs.toArray();
//清除标识位,设置为false
clearChanged();
}
//发送通知
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/**
* 删除订阅者
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
一定要调用这个方法,设置标识位为true,再调用notifyObservers才可以发送通知
*/
protected synchronized void setChanged() {
changed = true;
}
/**
清楚标识位,设置为false
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
获取标识位
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
获取订阅者数量
*/
public synchronized int countObservers() {
return obs.size();
}
}
观察者
public interface Observer {
/**
就一个方法更新在 上面notifyObservers 方法中有调用
*/
void update(Observable o, Object arg);
}
JAVA内置观察者实现
主题
package com.ghgcn.model.javaobserver2;
import java.util.Observable;
/**
* JAVA内置的主题
*
* @author Administrator
*
*/
public class SubjectDate extends Observable {
private float temperature;
private float humidity;
private float pressure;
public SubjectDate() {
super();
}
public SubjectDate(float temperature, float humidity, float pressure) {
super();
this.temperature = temperature;
this.humidity = humidity;
this.pressure = 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;
}
public void measurementsChanged(){
/**
* 发生改变
*/
setChanged(); //changed=true
/**
* 通知
*/
notifyObservers();
}
}
观察者
package com.ghgcn.model.javaobserver2;
import java.util.Observable;
import java.util.Observer;
import com.ghgcn.model.observer1.DispatyElement;
import com.ghgcn.model.observer1.WeatherDate;
public class CurrentDisplay implements DispatyElement, Observer {
private Observable subjectDate;
private float temperature;
private float humidity;
private float pressure;
public CurrentDisplay(Observable subjectDate) {
this.subjectDate = subjectDate;
subjectDate.addObserver(this);
}
public void update(Observable o, Object arg) {
if (o instanceof SubjectDate) {
SubjectDate sub = (SubjectDate)o;
this.temperature=sub.getTemperature();
this.humidity=sub.getHumidity();
this.pressure=sub.getHumidity();
display();
}
}
public void display() {
System.out.println("CurrentConditionsDisplay :\n temperature: " + this.temperature + " \n humidity:"
+ this.humidity + "\n pressure:" + this.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.ghgcn.model.javaobserver2;
import java.util.Observable;
import java.util.Observer;
import com.ghgcn.model.observer1.DispatyElement;
import com.ghgcn.model.observer1.WeatherDate;
public class CurrentDisplay2 implements DispatyElement, Observer {
private Observable subjectDate;
private float temperature;
private float humidity;
private float pressure;
public CurrentDisplay2(Observable subjectDate) {
this.subjectDate = subjectDate;
subjectDate.addObserver(this);
}
public void update(Observable o, Object arg) {
if (o instanceof SubjectDate) {
SubjectDate sub = (SubjectDate)o;
this.temperature=sub.getTemperature();
this.humidity=sub.getHumidity();
this.pressure=sub.getHumidity();
display();
}
}
public void display() {
System.out.println("CurrentDisplay2 :\n temperature: " + this.temperature + " \n humidity:"
+ this.humidity + "\n pressure:" + this.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.ghgcn.model.javaobserver2;
public interface DisplayElement {
public void display();
}
测试
package com.ghgcn.model.javaobserver2;
public class Test1 {
public static void main(String[] args) {
SubjectDate subjectDate = new SubjectDate(32.6f, 65.3f, 30.4f);
CurrentDisplay c1 = new CurrentDisplay(subjectDate);
CurrentDisplay2 c2 = new CurrentDisplay2(subjectDate);
subjectDate.measurementsChanged();
}
}
结果
CurrentDisplay2 :
temperature: 32.6
humidity:65.3
pressure:65.3
CurrentConditionsDisplay :
temperature: 32.6
humidity:65.3
pressure:65.3
并没有按订阅的顺序执行
网友评论