设计模式之观察者模式
一:观察者模式
定义一对多(1:n)的对象关系,如果1发生变化,那么n都会收到通知,这叫观察者模式。当然,我觉得叫”出版者——订阅者”模式更加容易理解。就像你在报社订了报纸,只要报社有新报纸出版,送报员就会给你家送一份,如果不想要,还可以退定。
二:来个栗子
举一个Head First书上的栗子:
首先这是一个气象局的显示系统,WeatherData是数据的来源,Subject是一个公共基础主题,Observer是观察者的父类。WeatherData的数据如果更新,我希望forecastObserver这个面板上的数据也更新,为了使结构简单,我没有添加xObserver和yObserver等其他的Observer,但是并不代表它们不存在(实际上是可以任意扩展的)。
当然,在系统中,WeatherData也只是数据变化的一部分,如果有两部分或者更多,我们可以继续有OtherData...,让它继承自Subject就好了。Subject中定义的方法addObserver可以被forecastObserver显式的调用将自己添加到WeatherData主题中,这样,WeatherData更新的数据就会在notifyobserver中以update的方式更新到forecastObserver中。
至于forecastObserver中的Subject sub元素,就是作为一个观察者,我最起码应该知道我订阅了谁的出版吧,即使以后去退订,也应该知道找谁(调用谁的方法)。
三:实现如下
Subject.java
public interface Subject {
public void addobserver(Observer ob);
public void delobserver(Observer ob);
public void notifyobserver();
}
Observer.java
public interface Observer {
public void update(int a,int b,int c);
}
WeatherData.java
public class WeatherData implements Subject {
private ArrayList arrayList = new ArrayList();
private int x;
private int y;
private int z;
public void addobserver(Observer ob) {
arrayList.add(ob);
}
public void delobserver(Observer ob) {
int i = arrayList.indexOf(ob);
if(i >= 0) {
arrayList.remove(i);
}
}
public void notifyobserver() {
for (int i = 0; i < arrayList.size(); i++) {
Observer ob = (Observer) arrayList.get(i);
ob.update(x,y,z);
}
}
public void setvalue(int a,int b,int c) {
this.x = a;
this.y = b;
this.z = c;
notifyobserver();
}
}
forecastObserver.java
public class forecastObserver implements Observer {
private Subject myobj;
private int x;
private int y;
public forecastObserver(Subject ob) {
this.myobj = ob; //保存自己的出版者
ob.addobserver(this);
}
public void update(int a, int b, int c) {
this.x = a;
this.y = b;
display();
}
public void display() {
System.out.println("x is " + x + " y is " + y);
}
}
main.java
public class main {
public static void main(String[] args) {
WeatherData wd = new WeatherData(); //定义出版者
forecastObserver fo = new forecastObserver(wd); //订阅者
wd.setvalue(1,2,3); //出版者不断变化新的数据
wd.setvalue(4,5,6);
wd.setvalue(7,8,9);
}
}
结果如下:
四:总结
好处:
- 面向接口编程,组合要比继承好。
- 无论是订阅者增加还是观察者增加都非常容易扩展。
缺点:
- 数据的更新是被动的。会将不需要的数据一并更新过来,比如上面栗子中
forecastObserver不需要z数据,但是Subject还是将数据更新过来了。
五:后续工作
- 将此模式更改为可以主动
拉数据的。 JDK内置观察者模式,改天试一试。
浙公网安备 33010602011771号