观察者模式的应用场景
来考虑实际生活中订阅报纸的过程,这里简单总结了一下订阅报纸的基本流程,(互联网时代很少人这样做哈)。
1.首先按照自己的需要选择合适的报纸,具体的报刊杂志目录可以从邮局获取。
2.选择好以后,就到邮局取填写订阅单,同时缴纳费用。
完了以后,就完成了订阅过程,就下来就是耐心等待了,报社会按照出报时间推出报纸,然后报纸会被送到每个订阅人手里。大致过程如下图所示。
从订阅者的角度来看,我们好像就是直接与邮局订阅的报纸,但是其实邮局差不多就是一个中介,邮局就拿着订阅信息交给报社,而报社会定期提供报纸。如果没有邮局这个“中间商”,其结构是怎么样的呢?
如下图所示:
订阅者最关心的问题
订阅者最关心的问题肯定就是报纸什么时候送到我手上了,虽然报纸都是定期出版的,但是如果报纸是不定期的呢?我们应该怎么解决?
时间不定
订阅者类向出版者类订阅报纸,很明显不止是一个订阅者,订阅者可以有很多个;当出版者类出版新报纸的时候,多少个订阅者?如何知道呢?订阅者如何得到新报纸的内容?
把上面的问题描述一下:
问题的解决方案
为了解决上述问题。我们将使用观察者模式。那什么是观察这模式呢?
观察者模式的定义:
定义对象间的一种一对多的依赖关系。当一个对象的状态发生改变时,所以依赖于它的对象都得到通知并被自动更新。
如果定义看不懂可以先看看例子,再倒回来看看观察者模式的定义
观察模式问题解决的思路
在前面说的订阅者的例子里,对于报社来说,在一开始,它并不清楚究竟有多少订阅者订阅报纸,所以报社需要维护一个订阅者列表,如此,当报社出版报纸的时候,才能够把报纸放到所有的订阅者手里。对于订阅者来说,订阅者也就看报的读者,多少个订阅者同时订阅改报纸。
这边出现了典型的一对多的对象关系,一个报纸可以被多个订阅者订阅。当报社出版的时候,也就是报纸对象改变的时候,需要通知所有的订阅者对象。如何建立并维护这样的关系?
那就交给观察者模式了。观察者模式把我们上述的订阅者设置成观察者:Observer,多个观察者观察的目标对象为:Subject
一个目标可以由多个观察者观察, 一旦目标发生了改变,所有的注册观察者都会得到通知,然后各个观察者会对通知作出相应的相应,执行相应的业务功能处理,并使自己的状态和目标对象的状态保持一致。
观察者结构说明:
Subject:目标对象
1.一个目标可以被多个观察者观察
2.目标提供观察者注册和退订的维护
3.当目标的状态发生改变时,目标负责通知所有注册、有效的观察者。
Observer:定义观察者的接口,提供目标目标更新时对应的更新方法,这个更新方法进行相应的业务处理,可以在这个方法里面回调目标对象,以获取目标对象的数据。
ConcreteSubject:具体的目标实现对象,用来维护目标状态,当目标对象的状态发生改变时,通知所有注册的、有效的观察者,让观察者处理执行相应的处理。
ConcreteObserver:观察者的具体实现对象,用来接收目标的通知,并进行相应的后续处理,比如更新自身的状态以保持和目标的相应状态一致。
久违的代码
1.先看看目标类的实现吧!具实现的细节都写在代码里,文字就不再有过多的描述了。
/**
* 目标对象,它知道观察它的观察者,并提供注册和删除观察者的接口
* @author Mr.Wang
*
*/
public class Subject {
/**
* 用来保存注册的观察者对象
*/
private List<Observer> observers = new ArrayList<>();
/**
* 注册一个观察者
* @param observer 观察者
*/
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
/**
* 通知所有观察者的方法
*/
public void notityfyObserver(){
for(Observer observer : observers) {
observer.update(this);
}
}
}
2.具体的目标对象类
public class ConcreateSubject extends Subject {
private String subjectState;//目标状态
public String getSubjectState() {
return subjectState;
}
/**
* 修改目标状态以后,通知所有观察者
* @param subjectState
*/
public void setSubjectState(String subjectState) {
this.subjectState = subjectState;//修改状态
this.notityfyObserver();//通知所有观察者
}
}
3.观察者类,其接口的定义
// 观察者接口,定义一个更新的接口给那些在目标发生改变的时候被通知的对象
public interface Observer {
/**
* 当得到目标类状态更新的时候,执行的更新方法
* @param subject 目标类
*/
public void update(Subject subject );
}
4.观察者的具体类
/**
* 具体观察者对象,实现更新方法,使自身的状态和目标的状态保持一致
* @author Mr.Wang
*
*/
public class ConcreteObserver implements Observer {
private String observerState;//观察者的状态
@Override
public void update(Subject subject) {
observerState = ((ConcreateSubject)subject).getSubjectState();
}
}
观察者模式,是在SpringIOC容器在创建Bean对象的过程中用于观察其创建过程处于那个阶段所使用到的一个设计模式,面试中也会碰到的,如果想更深入阅读Spring源码,可以了解其所以然。再去读一读Spring源码可能就会恍然大悟。如果解释足够清楚请点个赞。