什么是观察者模式
观察者模式其实在我们生活中特别常见。就像你和隔壁老王订阅了天气和杂志。当有新的信息更新时,你和隔壁老王都会接到通知。
高大上的说法就是基于Subject
这个概念,Subject
是一个特殊对象,就是类似上面的天气信息,是作为被观察的事物
,称为被观察者
。而订阅的Observers
,也就是你和老王,的称为观察者
。当Subject
保存的一系列信息被更新修改后就会通知所有定于的Observers
。
比较重要的一点是,观察者
之间是没什么关系的,他们可以属于各种各样的人群。
下面这图看不懂就先算了吧。。。回头再看
用Java动手写个观察者Demo呗
这里找一个场景。例如煎饼是在气象局工作。而煎饼的妈妈和女朋友(假装有女朋友)都订阅了煎饼的明天天气预报信息。到了等到煎饼第一时间知道天气信息更新的时候,就去通知她们两。
Observer模板
public interface IObserver<T> {
void update(T data);
}
而Observer模板使用接口,是因为上面说到订阅者可以使各种人群,所以他们只需要是实现Observer接口就可以了,而且Java是单继承的。不用接口的话下面就不能去继承了。。。
Observable模板
public class Observable<T> {
private T data;
private List<IObserver<T>> observerList = new ArrayList<>();
private final void attach(IObserver<T> observer) {
this.observerList.add(observer);
}
private final void detach(IObserver<T> observer) {
this.observerList.remove(observer);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
notifyDataChange();
}
private final void notifyDataChange() {
for (IObserver<T> observer : observerList) {
observer.update(data);
}
}
}
这里的Observable模板使用抽象类,因为当信息更新的时候。提醒的行为是不一样的。所以就让实现类去完成这工作。
Girl实现类
public class Girl implements IObserver<String> {
private String name;
private String something;
public Girl() {
}
public Girl(String name, String something) {
this.name = name;
this.something = something;
}
@Override
public void update(String data) {
System.out.println(data + ",你要和" + name + something + "。");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSomething() {
return something;
}
public void setSomething(String something) {
this.something = something;
}
}
上面就是妈妈和女朋友的
观察者
实现类,因为逻辑比较简单。所以并没有体现出观察者
来自不同的类
-
something
: 就是不同的观察者
对天气改变
做出的响应
调用
public static void main(String[] args) {
IObserver<String> mother = new Girl("妈妈", "购物");
IObserver<String> girlFriend = new Girl("女朋友", "约会");
Observable<String> jb = new Observable<>();
jb.attach(mother);
jb.attach(girlFriend);
jb.setData("今天天气晴朗,万里晴空");
}
结果
今天天气晴朗,万里晴空,你要和妈妈购物。
今天天气晴朗,万里晴空,你要和女朋友约会。
观察者在Java
上面是自己写的一个观察者Demo。其实Java里面早就给我们封装好了观察者和被观察者啊哈哈。。。我们看看吧。
注意一下导包,都是在java.util
下面的,别乱导。。。
Girl2(Observer)
public class Girl2 implements Observer {
private String name;
private String something;
public Girl2() {
}
public Girl2(String name, String something) {
this.name = name;
this.something = something;
}
@Override
public void update(Observable o, Object arg) {
System.out.println(arg + ",你要和" + name + something + "。");
}
}
JBWeather(Observable)
public class JBWeather extends Observable {
private String weather;
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
setChanged();
notifyObservers(weather);
}
}
调用
public static void main(String[] args) {
Observer mother = new Girl2("妈妈", "购物");
Observer girlFriend = new Girl2("女朋友", "约会");
JBWeather jb = new JBWeather();
jb.addObserver(mother);
jb.addObserver(girlFriend);
jb.setWeather("今天天气晴朗,万里晴空");
}
其实观察者模式中有两种推送数据的方法,一种是直接把需要的数据传给订阅者,一个是把自己送出去。。。其中
Observable
中的notifyObservers()
和notifyObservers(Object obj)
就是这个区别。给参数就只穿数据,不给参数就把自己传出去。我们也可以看到Observer
中的参数也是有两个的。。
还有就是更新信息别忘了setChanged
方法,我就是忘了这个,然后就找了很久,最后看了一下源码。。。gg了
什么时候用观察者
- 有两个实体类,一个的数据依赖另一个,你想让他们数据能够同步,但是又要相互独立,那就让他们成为观察者把。
- 当一个变化需要通知其他对象,,那就让他们成为观察者把。
- 当一个变化需要通知无法推断的对象,那就让他们成为观察者把。