本小仙女在开发道路上渣了两年多以后,突然回过头想把以前不太理解的东西再捯饬捯饬,虽然还是很渣,但是学习还是必要的,万一哪天成大神了呢。哇咔咔。。。。
一.定义
观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有观察者对象,使得他们能够自己更新自己。
其实,定义很好懂,就是说的只要一个被观察者发生一点变化,所有观察他的观察者能立马知道并且做出相应的反应。就拿广播机制举个例子吧。当你退出登录的时候,app中好多地方都要及时知道这一状态变化并及时做出反应,登录页面要变成未登录的状态,好多需要登录状态才能显示的模块要进行隐藏。所以在每个需要知道登录状态改变的地方我们去注册一个广播,当退出登录的时候发送广播,所有地方都能收到这一状态并及时做出响应。
二.图解
观察者模式让双方解除耦合,让耦合的双方都依赖于对象通知者一般用一个抽象类或者接口实现。下面看结构图(百度上拉下来的图,自己不会画)
观察者模式的四个角色
1.抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。一般是一个抽象类或者一个接口来实现,常见的方法attatch(),detach(),notifyObserver();java提供java.util.Observable类支持,
2.具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
3.抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。定义的方法有update(),Java提供了java.util.Observer接口支持,
4.具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。
三.举例讲解
由于本小仙女是一个android程序媛,所以例子也是android相关。接下来说说BaseAdapter。看下图.
其中标注1的地方定义了一个DataSetObservable对象mDataSetObservable,然后标注2的注册方法里把传入的DataSetObserver对象注册到mDataSetObservable中,同理标注3为解除注册,标注4是mDataSetObservable通知变化,咋一看,和观察者模式结构图Subject好像呢,那么接着往下看,这个DataSetObservable到底是啥,看下图
可以看出,DataSetObservable继承了Observable。红框框出来的notifyChanged()方法中,同步锁了mObservers这个对象,然后for循环这个对象,拿出对象中的对象调用onChanged()方法。我们继续看mObservers是什么,看下图
在Observable中,我们找到了mObservers,它是一个ArrayList对象,存放了好多T对象,那泛型T对象是啥,上一步中,DataSetObservable继承了Observable<DataSetObserver>,所以这里的mObservers里都是DataSetObserver对象,我们在看下DataSetObserver,上图
DataSetObserver是一个抽象类,里面有onChanged()和OnInvalidated()两个方法。
到这里,整个观察者模式的结构非常清晰,抽象类Observable是抽象主题角色,DataSetObservable是一个具体主题角色,抽象类DataSetObserver是抽象观察者角色,程序员在需要的地方创建一个具体观察者角色继承DataSetObserver,然后调用BaseAdapte的registerDataSetObeserver。整个观察者模式就完美了,哈哈。
四.其他
其他使用到观察者模式的场景OnClickListener、ContentObserver、android.database.Observable等;还有组件通讯库RxJava、RxAndroid、EventBus。好说完手工。哈哈。