*本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布
写在前面
最近在学习 EventBus 和 RxJava 相关知识,了解到两者都使用了观察者模式。以前对该模式只有一个模糊的概念,导致看 E 和 R 时一知半解,所以下定决心把这个模式仔细回顾和记录一下。
一、观察者模式相关概念
定义:一个对象和多个形成依赖关系,当一个对象改变状态,所以依赖于它的对象都会得到通知并执行相应逻辑。
简单理解:A 是被观察者,B、C、D 是观察者。当 A 发生变化时发出通知告知 B、C、D,然后 B、C、D 可根据 A 发送的数据来做具体的事情。
重要作用:解耦。也就是将观察者和被观察者解耦。
解耦的好处不用多说,设计模式中 单一职责原则 也表明我们希望每个实体(类、函数、模块等)能引起其改变的原因只有它自己。
也就是说,我们希望观察者的逻辑和被观察者的逻辑是分离的。
使用场景:
1.某些时候需要一些对象有所关联,而且这种关联是可以拆分而不是组合在一起的。
2.某一事件发生,需要向多方触发。
3.消息交换,如消息队列、事件总线的处理机制。
UML 类图
观察者模式主要角色:
- Subject:抽象主题,被观察者(Observable)的抽象,管理着众多观察者的实现,可以实现添加或删除观察者的功能。
- ConcreteSubject:具体主题,被观察者(Observable)的实现,通过该实现来向观察者发送通知。
- Observer:抽象观察者(Observer),观察者的抽象。一般是接口,实现该接口生成各种各样的观察者。
- ConcreteObserver:具体观察者,抽象观察者的具体实现,当被观察者发生变化时执行具体逻辑。
概念理解起来确实比较麻烦,但是结合具体的例子来理解的话会好很多,下面就是一个简单的例子。
二、观察者模式简单实现
要实现的功能:定义一个数据源,当数据源发生变化时,其它所有观察者收到消息并更新 UI。
具体步骤:
- 定义一个数据源 DataSource,继承 Observable。Observable 属于观察者模式中的抽象主题(Subject),那么这个实现类 DataSource 就是具体主题(ConcreteSubject)了。
这个实现类的具体作用是作为被观察者,当它的数据发生变化时去通知所有观察者。
/**
* 数据源,被观察者
*/
public class DataSource extends Observable {
// 数据发生变化时调用该方法通知观察者
public void updateData(String content){
// 标记状态或内容已经发生改变
setChanged();
// 通知所有观察者
notifyObservers(content);
}
}
- 首先定义一个更新数据的方法
updateData()
,参数是可以被观察者接收的任意类型。
这里定义的是 String 类型的,因为我的观察者是自定义 TextView,需要 String 来更新数据。 -
setChanged()
这个是父类 Observable 中的方法,用来改变一个标记,表明数据已经更新。后面会根据该标记来决定是否通知所有观察者。 -
notifyObservers(content)
父类中的方法,该方法会调用所有观察者的update()
方法实现数据的传递更新。
- 定义观察者 MyTextView,这是我自己定义的 TextView,实现了 Observer 接口。
Observer 接口就是抽象观察者了,那么这里的实现类 MyTextView 就是具体观察者角色(ConcreteObserver)了。
/**
* 观察者,自定义 TextView,监听数据变化
*/
public class MyTextView extends TextView implements Observer {
// 自定义 View 三个构造函数
public MyTextView(Context context) {
this(context,null);
}
public MyTextView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
// 父类 Observer 中的方法,当调用 notifyObservers 时调用
@Override
public void update(Observable o, Object arg) {
setText(arg.toString());
}
}
- 自定义 TextView,三个构造函数不多说。
-
update(Observable o, Object arg)
方法是接口 Observer 中的方法,参数Observable o
是具体的观察者类,Object arg
是具体的数据。
- 定义 ObserverTestActivity,布局中写个 Button 模拟数据发生变化。接着使用刚才自定义的 MyTextView,这里写了两个。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.sky.viewtest.ObserverTestActivity">
<Button
android:id="@+id/btn_change"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="数据变化"/>
<com.sky.viewtest.design_pattern.MyTextView
android:id="@+id/tv_text1"
android:layout_width="match_parent"
android:layout_height="30dp"
android:gravity="center"/>
<com.sky.viewtest.design_pattern.MyTextView
android:id="@+id/tv_text2"
android:layout_width="match_parent"
android:gravity="center"
android:layout_height="30dp" />
</LinearLayout>
- 模拟数据变化并通知 UI。
public class ObserverTestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_observer);
// 模拟数据变化
findViewById(R.id.btn_change).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
changeData();
}
});
}
private void changeData(){
// 创建具体的被观察者类实例
DataSource dataSource = new DataSource();
MyTextView myTextView1 = (MyTextView) findViewById(R.id.tv_text1);
MyTextView myTextView2 = (MyTextView) findViewById(R.id.tv_text2);
// 添加观察者
dataSource.addObserver(myTextView1);
dataSource.addObserver(myTextView2);
// 通知所有观察者数据更新
dataSource.updateData("数据变化啦");
}
}
- 要注意的是只有把所有被观察者使用
addObserver()
添加进来才会收到后续数据更新。
效果:
当我点击按钮时,两个 TextView 的数据都发生了变化。
三、源码分析
结合上文例子分析 java.util 包下的 Observer 和 Observable 的实现。
接口 Observer
public interface Observer {
void update(Observable o, Object arg);
}
- 很简单的一个接口,只定义了一个
update()
方法,参数 Observable 和 Object。
Observable o
表示具体的被观察者对象,Object arg
是要传递和更新的数据。 - 上文 MyTextView 实现该接口,并实现
update()
方法。该方法的作用是当 DataSource 发生数据变化时,会遍历所有已添加的 MyTextView 并调用它们的update()
方法来更新 UI。
类 Observable
public class Observable {
// 1.1 数据是否变化标记
private boolean changed = false;
// 1.2 长度自增长数组
private Vector<Observer> obs;
/** Construct an Observable with zero Observers. */
public Observable() {
obs = new Vector<>();
}
// 2.1 添加观察者对象
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
// 2.2 删除观察者对象
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
// 3.1 通知所有观察者
public void notifyObservers() {
notifyObservers(null);
}
public void notifyObservers(Object arg) {
Object[] arrLocal;
// 线程同步
synchronized (this) {
// 3.2 获取是否发生变化的标记
if (!hasChanged())
return;
// 3.3 转化为 Object 数组
arrLocal = obs.toArray();
// 重置标记
clearChanged();
}
// 遍历所有观察者并调用其 update 方法
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
// 删除所有观察者对象
public synchronized void deleteObservers() {
obs.removeAllElements();
}
// 设置标记为 true,表明数据发生了变化且已经通知过
protected synchronized void setChanged() {
changed = true;
}
// 清除标记,恢复默认状态
protected synchronized void clearChanged() {
changed = false;
}
// 获取标记
public synchronized boolean hasChanged() {
return changed;
}
// 获取观察者的数量
public synchronized int countObservers() {
return obs.size();
}
}
该类比较简单,按注释顺序来看:
- 两个变量
changed
和obs
。changed
是数据是否变化的标记,主要作用是避免重复通知观察者。obs
是一个自增长的数组,用来存放具体的观察者对象,也就是实现了 Observer 的实现类。
这里有一个知识点:设计模式的 依赖倒置原则:面向接口编程而不是面向具体对象编程。这个obs
数组存放的是接口类型而不是某个具体实现类型表明了这一点。 - 添加和删除观察者对象的方法就是往数组 obs 添加和删除元素。
- 3.1
notifyObservers()
通知所有观察者,可以看到该函数使用了 synchronized 保证线程安全,然后hasChanged()
获取当前标记状态,如果标记为 false 则 return 不进行通知。
3.2 那么这个标记什么时候才能为 true 呢?是在该类的子类中,也就是刚才例子中 DataSource 数据源类updateData()
方法中首先调用setChanged()
来设置标记为 true,表明数据即将进行更新。
3.3 之后将数组 obs 转化为 Object 数组,设置标记为 false,然后遍历 obs 数组并调用所有元素的 update() 方法。也就是例子中所有添加进来的 MyTextView 对象的update()
方法都会被调用,所有 MyTextView 的 text 发生变化。
到这里 Observer(抽象观察者) 和 Observable(抽象被观察者)已经分析的差不多了,那么再结合刚才的例子来总结一下:
- MyTextView 实现 Observer,是具体的观察者。实现方法
update()
来执行具体的逻辑。 - DataSource 继承 Observable,是具体的被观察者。通过
notifyObservers()
方法传递具体数据来实现通知所有观察者,传递的具体逻辑是在父类中实现的。 - Observable 作为抽象被观察者实现具体的数据传递逻辑,其内部维护了一个标记和具体观察者列表,当数据发生变化时遍历该列表并通过调用
update()
方法来通知具体观察者实现不同的逻辑。
四、观察者模式在 RecyclerView 中的体现
通过以上对观察者模式的了解,四个主要角色 抽象观察者、具体观察者、抽象被观察者和具体观察者 起到了重要作用,而他们的运作是通过三个重要方法 注册观察者、解除注册、发送通知,那么分析 RecyclerView 也要从这几点入手。
首先我们知道 RecyclerView 中使用了观察者模式(和 ListView 类似),也知道 notifyDataSetChanged()
起到通知界面刷新的功能,那么就从这个方法入手。
RecyclerView.Adapter<VH extends ViewHolder> # notifyDataSetChanged()
public abstract static class Adapter<VH extends RecyclerView.ViewHolder> {
private final RecyclerView.AdapterDataObservable mObservable = new RecyclerView.AdapterDataObservable();
...
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
...
}
这个方法其实是在 RecyclerView 的内部静态抽象类 Adapter<VH extends ViewHolder> 中,可以看到 notifyDataSetChanged()
实际调用了 Adapter 的成员变量 mObservable 的 notifyChanged()
方法,该方法的实现暂且不管。这个变量 mObservable 命名方式很熟悉,那么就去看一下这个 AdapterDataObservable 类吧。
static class AdapterDataObservable extends Observable<AdapterDataObserver>
这个类继承了 Observable,看样子是一个被观察者实现类,为了验证一下,去看看 Observable 类。
类 Observable
package android.database;
import java.util.ArrayList;
/**
* Provides methods for registering or unregistering arbitrary observers in an {@link ArrayList}.
*
* This abstract class is intended to be subclassed and specialized to maintain
* a registry of observers of specific types and dispatch notifications to them.
*
* @param T The observer type.
*/
public abstract class Observable<T> {
/**
* The list of observers. An observer can be in the list at most
* once and will never be null.
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* Adds an observer to the list. The observer cannot be null and it must not already
* be registered.
* @param observer the observer to register
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is already registered
*/
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
/**
* Removes a previously registered observer. The observer must not be null and it
* must already have been registered.
* @param observer the observer to unregister
* @throws IllegalArgumentException the observer is null
* @throws IllegalStateException the observer is not yet registered
*/
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
/**
* Remove all registered observers.
*/
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
- 我特意把包名也贴出来了,它不是 java 里的 Observable,而是 Android 自己的实现。
-
protected final ArrayList<T> mObservers = new ArrayList<T>();
:根据这个 ArrayList 可以看出该类维护了一个<T>类列表,那么这<T>类应该就是具体观察者了。 -
registerObserver()
、unregisterObserver()
、unregisterAll()
符合抽象被观察者管理具体观察者的逻辑,所以这个类就是抽象被观察者角色了。
这样就可以确定刚才 RecyclerView.AdapterDataObservable 是一个具体被观察者了。理一下现在得到的逻辑:
public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 {
// 为了方便理解我打乱了顺序,不要钻牛角尖
// 1. AdapterDataObservable:具体被观察者 Observable:抽象被观察者
static class AdapterDataObservable extends Observable<AdapterDataObserver> {
//3.mObservable.notifyChanged()
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}
...
public abstract static class Adapter<VH extends ViewHolder> {
//2. 具体被观察者实例 mObservable
private final AdapterDataObservable mObservable = new AdapterDataObservable();
...
public final void notifyDataSetChanged() {
mObservable.notifyChanged();
}
}
}
- RecyclerView 静态内部类 AdapterDataObservable 是具体被观察者,Observable 类是 抽象被观察者,他们管理着具体观察者。
- Adapter 中持有具体被观察者实例 mObservable。
- 我们调用
notifyDataSetChanged()
实际调用了 具体被观察者实例 mObservable 的notifyChanged()
方法。
那么接下来分析一下 mObservable.notifyChanged();
干了什么:
AdapterDataObservable # notifyChanged()
public void notifyChanged() {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
这个方法做的事情很简单,遍历 mObservers,获取其中的具体观察者并调用他们的 onChanged()
方法达到发送通知的目的。这个 mObservers 其实是一个 ArrayList,是由抽象被观察者(Observable)管理的列表,在刚才的 Observable 类中早就定义好了。
在这里找到了发送通知的方法,遍历所有的具体观察者并调用他们的 onChanged()
方法,那么再看一下 onChanged()
方法的实现:
public abstract static class AdapterDataObserver {
public void onChanged() {
// Do nothing
}
...
}
可以看到是抽象类的空实现,那么就去找它的实现类,Ctrl+F 搜索 "extends AdapterDataObserver"。欧耶找到了,这就说明实现类也定义本类中。其实大多数实现类并不在本类中,这个小技巧也就是偶尔取巧用得上(#滑稽)。
类 RecyclerViewDataObserver
private class RecyclerViewDataObserver extends AdapterDataObserver {
RecyclerViewDataObserver() {
}
@Override
public void onChanged() {
assertNotInLayoutOrScroll(null);
mState.mStructureChanged = true;
setDataSetChangedAfterLayout();
if (!mAdapterHelper.hasPendingUpdates()) {
requestLayout();
}
}
...
}
可以看到重写的 onChanged()
中调用了 requestLayout()
申请重新布局,至于怎样实现,感兴趣的同学可以参考我另一篇文章:
那么回到正题,RecyclerViewDataObserver 实现了抽象类 AdapterDataObserver 的方法并被具体被观察者调用通知。那么可以得出结论:AdapterDataObserver 是抽象观察者,抽象出各种通知方法。RecyclerViewDataObserver 是具体观察者,实现抽象观察者中的方法执行具体逻辑。
这样四个角色都找齐了,三个方法只找到了发送通知的。还差注册和解除观察者的方法,这两个方法在 setAdapter 中所体现:
RecyclerView # setAdapter()
public void setAdapter(Adapter adapter) {
// bail out if layout is frozen
setLayoutFrozen(false);
setAdapterInternal(adapter, false, true);
requestLayout();
}
注册和解除观察者实际是在 setAdapterInternal() 中:
RecyclerView # setAdapterInternal()
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
boolean removeAndRecycleViews) {
//1.第一个 if
if (mAdapter != null) {
mAdapter.unregisterAdapterDataObserver(mObserver);
mAdapter.onDetachedFromRecyclerView(this);
}
if (!compatibleWithPrevious || removeAndRecycleViews) {
removeAndRecycleViews();
}
mAdapterHelper.reset();
final Adapter oldAdapter = mAdapter;
mAdapter = adapter;
//2.为新的 adapter 注册观察者
if (adapter != null) {
adapter.registerAdapterDataObserver(mObserver);
adapter.onAttachedToRecyclerView(this);
}
if (mLayout != null) {
mLayout.onAdapterChanged(oldAdapter, mAdapter);
}
mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
mState.mStructureChanged = true;
markKnownViewsInvalid();
}
上面的代码主要关注的是下面两点:
- 第一个 if 中如果 mAdapter 不为 null,也就是重新设置 RecyclerView 的 adapter 时先解除旧的观察者对象。
- 为新的 adapter 注册观察者。
- 注意这里传递的参数 mObserver 是 RecyclerViewDataObserver 类型的,这个类是具体观察者。
mAdapter.unregisterAdapterDataObserver
旧的 adapter 解除注册,adapter.registerAdapterDataObserver(mObserver);
新的 adapter 注册具体观察者。
Adapter # registerAdapterDataObserver()、unregisterAdapterDataObserver()
public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
mObservable.unregisterObserver(observer);
}
public void registerAdapterDataObserver(AdapterDataObserver observer) {
mObservable.registerObserver(observer);
}
可以看到解除和注册的方法是通过 Adapter 中保存的具体被观察者对象实例(mObservable)调用父类抽象被观察者(Observable)中的注册和解除观察者来完成的。
先看传递过来的参数类型是 AdapterDataObserver,也就是我们的抽象观察者,也就说明了抽象被观察者中维护的 ArrayList<T> mObservers 的这个 <T> 就是 AdapterDataObserver。而这个 ArrayList 具体保存的是 AdapterDataObserver 的实现类 RecyclerViewDataObserver。
这一块我表达的可能不够清晰,那么这里的逻辑再理清一下:
在 setAdapter() 的过程中,将具体观察者类的实例 mObserver 作为参数传递,用于设置具体的观察者。然后
调用 Adapter 中的 registerAdapterDataObserver(AdapterDataObserver observer)
方法进行注册,因为 mObserver 是 AdapterDataObserver 的子类实例,所以可以接收。
接着再通过 Adapter 中的 具体被观察者实例 mObservable 调用父类 Observable 中的注册和解除注册方法处理逻辑。
到这里就差不多完成了整个过程:
- 抽象被观察者:Observable<T>
- 具体被观察者:AdapterDataObservable
- 抽象观察者:AdapterDataObserver
- 具体观察者:RecyclerViewDataObserver
- 注册:registerAdapterDataObserver()
- 解除注册:unregisterAdapterDataObserver()
- 发送消息:notifyDataSetChanged() --> mObservable.notifyChanged() --> mObservers.get(i).onChanged()
五、观察者模式其它实现
观察者模式除了上文 java 包中的实现外,还有其它实现方式。话说回来,只要大方向不错,根据实际需求去定制设计模式和代码或许更好。
这里记录一下百度百科中记录的观察者模式 Demo。
- 首先是抽象主题,被观察者抽象:
//被观察者(一个抽象类,方便扩展)
public abstract class Observable{
public final ArrayList<Class<?>> obserList = new ArrayList<Class<?>>();
/**AttachObserver(通过实例注册观察者)
*<b>Notice:</b>obcan'tbenull,oritwillthrowNullPointerException
**/
public<T> void registerObserver(T ob){
if(ob==null) throw new NullPointerException();
this.registerObserver(ob.getClass());
}
/**
*AttachObserver(通过Class注册观察者)
*@paramcls
*/
public void registerObserver(Class<?> cls){
if(cls==null) throw new NullPointerException();
synchronized(obserList){
if(!obserList.contains(cls)){
obserList.add(cls);
}
}
}
/**UnattachObserver(注销观察者)
*<b>Notice:</b>
*<b>ItreverseswithattachObserver()method</b>
**/
public<T>void unRegisterObserver(Tob){
if(ob==null) throw new NullPointerException();
this.unRegisterObserver(ob.getClass());
}
/**UnattachObserver(注销观察者,有时候在未获取到实例使用)
*<b>Notice:</b>
*<b>ItreverseswithattachObserver()method</b>
**/
public void unRegisterObserver(Class<?>cls){
if(cls==null) throw new NullPointerException();
synchronized(obserList){
Iterator<Class<?>>iterator=obserList.iterator();
while(iterator.hasNext()){
if(iterator.next().getName().equals(cls.getName())){
iterator.remove();
break;
}
}
}
}
/**detachallobservers*/
public void unRegisterAll(){
synchronized(obserList){
obserList.clear();
}
}
/**Ruturnthesizeofobservers*/
public int countObservers(){
synchronized(obserList){
returnobserList.size();
}
}
/**
*notify all observer(通知所有观察者,在子类中实现)
*@paramobjs
*/
public abstract void notifyObservers(Object... objs);
/**
*notify one certain observer(通知某一个确定的观察者)
*@paramcls
*@paramobjs
*/
public abstract void notifyObserver(Class<?> cls, Object... objs);
/**
*notifyonecertainobserver
*@paramcls
*@paramobjs
*/
public abstract<T> void notifyObserver(T t, Object... objs);
}
从上面代码可以看出:
-
ArrayList<Class<?>> obserList
:观察者列表,Observable 维护着所有抽象观察者。 -
registerObserver()
、unRegisterObserver()
:Observable 包含添加和移除观察者对象的方法。 -
notifyObservers()
:通知所有观察者的函数,可以自己实现来统一管理,也可以交给子类去实现。这里是抽象方法,由子类实现。
- 抽象观察者,定义更新方法
//观察者,需要用到观察者模式的类需实现此接口
public interface Observer{
void update(Object...objs);
}
- 具体被观察者,继承 Observable 类。
//目标被观察者
public class ConcreteObservable extends Observable{
private static ConcreteObservableinstance = null;
private ConcreteObservable(){};
public static synchronized ConcreteObservablegetInstance(){
if(instance == null){
instance=newConcreteObservable();
}
returninstance;
}
@Override
public <T> void notifyObserver(T t, Object... objs){
if(t == null) throw new NullPointerException();
this.notifyObserver(t.getClass(), objs);
}
@Override
public void notifyObservers(Object... objs){
for(Class<?>cls : obserList){
this.notifyObserver(cls, objs);
}
}
//通过java反射机制实现调用
@Override
public void notifyObserver(Class<?>cls, Object...objs){
if(cls == null) throw new NullPointerException();
Method[] methods = cls.getDeclaredMethods();
for(Method method : methods){
if(method.getName().equals("update")){
try{
method.invoke(cls,objs);
break;
}catch(IllegalArgumentException e){
e.printStackTrace();
}catch(IllegalAccessException e){
e.printStackTrace();
}catch(InvocationTargetException e){
e.printStackTrace();
}
}
}
}
}
-
notifyObserver()
:实现父类抽象方法notifyObserver()
,遍历所有观察者,通过 java 反射机制调用具体观察中类的方法。
- 具体观察者类,需要添加到抽象被观察者维护的列表中。
//使用(实现Observer接口)
public class Text extends Activity implements Observer{
publicvoidonCreate(...){
ConcreteObservable.getInstance().registerObserver(Text.class);
....
}
//实现接口处理
publicvoidupdate(Object...objs){
//做操作,比如更新数据,更新UI等
}
}
六、总结
综上,只有找到四个重要角色:抽象观察者、具体观察者、抽象被观察者和具体观察者,以及三个方法:注册、解除注册和发送通知,就可以理清观察者模式的应用了。
观察者模式的优点:
- 解耦:
观察者和被观察者之间建立的是一个抽象的耦合,被观察者并不需要了解每一个具体的观察者,但是可以通过共同的接口来控制它们。 - 扩展性高:
如果需要创建新的观察者,只需要实现观察者抽象接口即可。
观察者模式的缺点:
- 效率问题:
如果观察者数量过多,遍历并按顺序执行它们的方法会产生效率问题。或者某个观察者所执行的代码过于繁琐,影响其他观察者信息或数据的接收。
有关观察者模式的记录就先到这里,在学会这些知识后灵活运用才是最重要的。个人觉得没有最好的代码,只有最合适的代码。
参考资料:
《Android源码设计模式解析与实战》