观察者模式
什么是观察者模式
- 出版者(Subject)+订阅者(Observer)=观察者模式
- Subject管理某些数据,当数据发生改变,新的数据就会以某种形式送到Observer手上
- Observer在订阅(register)主题以便在主题改变时收到更新
- 观察者模式定义对象之间的一对多依赖,当一个对象改变状态时,它的所有依赖者都收到通知并自动更新
- 松耦合 任何情况下我们可以添加/删除观察者,主题不会受到任何影响,改变主题或观察者其中一方,并不会影响另一方。只要接口仍被遵守,就可以自由改变他们
代码分析
public interface ISubject {
/*主题要为它的订阅者提供信息更新服务*/
void measureChange();
/*注册/订阅,observer可以订阅这个主题,可以得到这个主题的数据*/
void addObserver(IObserve io);
/*退订,observer可以取消订阅这个主题,不会再收到主题的数据*/
void deleteObserver(int i);
}
public interface IObserve {
/*主题可以调用订阅者接口的update方法使数据更新*/
void update(double t,double h,double p);
}
import java.util.ArrayList;
public class WeatherData implements ISubject {
/*主题仅仅知道有一个订阅者的名单*/
private ArrayList<IObserve> iObserveArrayList;
/*数据*/
private double t;
private double h;
private double p;
WeatherData(){
iObserveArrayList = new ArrayList<>();
}
/*数据更新,主题把所有数据都提供给订阅者供它选择*/
@Override
public void measureChange() {
for(IObserve i:iObserveArrayList){
i.update(t,h,p);
}
}
/*添加订阅者*/
@Override
public void addObserver(IObserve io) {
iObserveArrayList.add(io);
}
/*删除订阅者*/
@Override
public void deleteObserver(int i) {
iObserveArrayList.remove(i);
}
/*模拟数据更新的测试方法*/
public void setT(double t) {
this.t = t;
}
public void setH(double h) {
this.h = h;
}
public void setP(double p) {
this.p = p;
}
}
public class Display01 implements IObserve {
private double t;
private double h;
private double p;
/*类构造出来同时注册成为订阅者*/
Display01(ISubject is){
is.addObserver(this);
}
/*接收所有的更新数据*/
@Override
public void update(double t, double h, double p) {
this.t = t;
this.h = h;
this.p = p;
}
public void print(){
System.out.println("["+t+"]"+"["+h+"]"+"["+p+"]");
}
}
public class Main {
//push
public static void main(String[] args) {
WeatherData is = new WeatherData();
Display01 d = new Display01(is);
is.setH(10.1);
is.setP(30.5);
is.setT(75);
is.measureChange();
d.print();
}
}
- 主题将所有的信息"push"给了订阅者,订阅者选择信息进行处理
- 当然另一种方式可以"pull",订阅者向主题请求需要的信息
Java中也有实现的观察者模式的api,可惜采用的是继承的模式,在java9中已弃用
import java.util.Observable;
/*主题类,采用继承,类库Observable*/
public class WeatherData extends Observable {
/*数据*/
private double t;
private double h;
private double p;
WeatherData(){ }
/*数据更新*/
public void measureChange() {
/*setChanged()将Observable中的标志置为true*/
/*在notifyObservers()中将被检测标志,为true就会更新*/
/*所以在进行更新的时候必须调用setChanged()方法*/
setChanged();
notifyObservers();
}
/*模拟更新*/
public void setT(double t) {
this.t = t;
}
public void setH(double h) {
this.h = h;
}
public void setP(double p) {
this.p = p;
}
public double getT() {
return t;
}
public double getH() {
return h;
}
public double getP() {
return p;
}
}
import java.util.Observable;
import java.util.Observer;
/*订阅者*/
public class Display02 implements Observer {
/*主题对象,提供注册*/
private Observable o;
private double t;
private double h;
private double p;
/*构造并注册*/
public Display02(Observable o) {
this.o = o;
o.addObserver(this);
}
/*更新*/
/*这里其实不知道算不算"pull",由订阅者选择信息*/
@Override
public void update(Observable o, Object arg) {
if(o instanceof WeatherData) {
WeatherData w = (WeatherData) o;
this.h = w.getH();
this.p = w.getP();
this.t = w.getT();
}
}
public void print(){
System.out.println("["+t+"]"+"["+h+"]"+"["+p+"]");
}
}
public class Main {
public static void main(String[] args) {
//pull
WeatherData w = new WeatherData();
Display02 d = new Display02(w);
w.setH(12.4);
w.setP(45.1);
w.setT(4);
w.measureChange();
d.print();
}
}
- 上述使用java.util.Observable,java.util.Observer的某些方法,其他方法查询api
- 上述写了我理解中的"pull",可能有偏差
以上