如果我们现在向一家报社订阅了一份报纸,那么这家报社不管今天我们有没有心情看报纸,它都会把报纸送过来。有一天我们实在是不想看这家的报纸了,我们如果取消了订阅,那么从此以后报社再也不会送报纸到我们家了。
上面这一段情景,其实和观察者模式的工作性质是一样的。
观察者模式
定义:在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新。
其实就是有人发布信息,订阅的人都会收到通知,没订阅则不会收到通知。
- 主题(Subject):主题类,发生改变时将给所有的观察者发布信息
- 订阅者(Observer):订阅者,当主题改变时如果订阅了主题则会收到通知
例子
有粉丝关注了自己喜欢偶像的微博,一旦这个偶像微博动态发生了更新,那么粉丝就会接受到消息。
主题接口:
package observer;
/**
* 主题接口
* 有添加,删除,通知方法。
*/
public interface Observerable { ;
void registerObserver(Observer observer);
void removeObserver(Observer observer);
void notifyAllObersers();
}
观察者接口:
package observer;
/**
* 观察者接口
* 有更新方法
*/
public interface Observer {
void update();
}
具体实现主题(明星):
package observer;
import java.util.ArrayList;
/**
* 明星,一旦有风吹草动,粉丝立刻知晓。
*/
public class Star implements Observerable {
private ArrayList<Observer> observers = new ArrayList<>();
@Override
public void registerObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyAllObersers() {
for(Observer o : observers){
o.update();
}
}
}
具体实现观察者(粉丝):
package observer;
/**
* 粉丝,关注明星一举一动。
*/
public class Fans implements Observer {
private Observerable star;
private String name;
public Fans(Observerable star,String name) {
this.name = name;
this.star = star;
star.registerObserver(this);
}
@Override
public void update() {
System.out.println(this.name + " love my idol!!");
}
}
测试
package test.observer;
import observer.Fans;
import observer.Observer;
import observer.Observerable;
import observer.Star;
public class test {
public static void main(String args[]){
Observerable star = new Star();
Observer fans1 = new Fans(star,"Xiaohong");
Observer fans2 = new Fans(star,"Xiaoming");
Observer fans3 = new Fans(star,"Xiaolan");
star.notifyAllObersers();
star.removeObserver(fans3);
star.removeObserver(fans2);
star.notifyAllObersers();
}
}
结语
在JDK中已经有了Observable与Observer,但是很遗憾,Observable是一个类,而不是一个接口,所以当类继承它时,扩展性将会变得极差,限制了它的使用和复用,但是Observable内有一个setChanged方法,可以来以此借助状态判断是否通知观察者,比较灵活,若自己实现主体接口的话,可以借鉴这种做法,有兴趣的同学可以自己查看JDK的源代码,在util包中。
在该设计模式中,体现了一个设计原则,即:
为交互对象之间的松耦合而努力
我们可以在观察者模式中明显的感受到,主题和观察者之间的松耦合。
主体只知道观察者实现了某个接口(即Observer),不需要知道观察者是谁,做了些什么或者其他细节,唯一依赖的是一个观察者的列表。假设有个新的类想当观察者,我们不需要更改主体的代码,只需新类实现接口,并注册到列表中去,这样的系统十分具有弹性,两者间的耦合降到了最低。
源码在这里:我的github地址