2018/5/18 18:08:16当前位置推荐好文程序员浏览文章

本篇文章已受权微信公众号 guolin_blog (郭霖)独家发布

写在前面

最近在学习 EventBus 和 RxJava 相关知识,理解到两者都用了观察者模式。以前对该模式只有一个模糊的概念,导致看 E 和 R 时一知半解,所以下定决心把这个模式仔细回顾和记录一下。

一、观察者模式相关概念

定义:一个对象和多个形成依赖关系,当一个对象改变状态,所以依赖于它的对象都会得到通知并执行相应逻辑。

简单了解:A 是被观察者,B、C、D 是观察者。当 A 发生变化时发出通知告知 B、C、D,而后 B、C、D 可根据 A 发送的数据来做具体的事情。

重要作使用:解耦。也就是将观察者和被观察者解耦。

解耦的好处不使用多说,设计模式中 单一职责准则 也表明我们希望每个实体(类、函数、板块等)可以引起其改变的起因只有它自己。
也就是说,我们希望观察者的逻辑和被观察者的逻辑是分离的。

用场景:
1.某些时候需要少量对象有所关联,而且这种关联是能拆分而不是组合在一起的。
2.某一事件发生,需要向多方触发。
3.消息交换,如消息队列、事件总线的解决机制。

UML 类图

观察者模式.png

观察者模式主要角色:

  1. Subject:笼统主题,被观察者(Observable)的笼统,管理着众多观察者的实现,能实现增加或者删除观察者的功可以。
  2. ConcreteSubject:具体主题,被观察者(Observable)的实现,通过该实现来向观察者发送通知。
  3. Observer:笼统观察者(Observer),观察者的笼统。一般是接口,实现该接口生成各种各样的观察者。
  4. ConcreteObserver:具体观察者,笼统观察者的具体实现,当被观察者发生变化时执行具体逻辑。

概念了解起来的确比较麻烦,但是结合具体的例子来了解的话会好很多,下面就是一个简单的例子。

二、观察者模式简单实现

要实现的功可以:定义一个数据源,当数据源发生变化时,其它所有观察者收到消息并升级 UI。

具体步骤:
  1. 定义一个数据源 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() 方法实现数据的传递升级。
  1. 定义观察者 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是具体的数据。
  1. 定义 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>
  1. 模拟数据变化并通知 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 的数据都发生了变化。


Test.png
三、源码分析

结合上文例子分析 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();        }        // 遍历所有观察者并调使用其 方法        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();    }}

该类比较简单,按注释顺序来看:

  1. 两个变量 changedobschanged是数据能否变化的标记,主要作使用是避免重复通知观察者。obs是一个自增长的数组,使用来存放具体的观察者对象,也就是实现了 Observer 的实现类。
    这里有一个知识点:设计模式的 依赖倒置准则:面向接口编程而不是面向具体对象编程。这个 obs 数组存放的是接口类型而不是某个具体实现类型表明了这一点。
  2. 增加和删除观察者对象的方法就是往数组 obs 增加和删除元素。
  3. 3.1notifyObservers() 通知所有观察者,能看到该函数用了 synchronized 保证线程安全,而后 hasChanged() 获取当前标记状态,假如标记为 false 则 return 不进行通知。
    3.2 那么这个标记什么时候才可以为 true 呢?是在该类的子类中,也就是刚才例子中 DataSource 数据源类 updateData() 方法中首先调使用 setChanged() 来设置标记为 true,表明数据即将进行升级。
    3.3 之后将数组 obs 转化为 Object 数组,设置标记为 false,而后遍历 obs 数组并调使用所有元素的 update() 方法。也就是例子中所有增加进来的 MyTextView 对象的 update() 方法都会被调使用,所有 MyTextView 的 text 发生变化。

到这里 Observer(笼统观察者) 和 Observable(笼统被观察者)已经分析的差不多了,那么再结合刚才的例子来总结一下:

  1. MyTextView 实现 Observer,是具体的观察者。实现方法 update() 来执行具体的逻辑。
  2. DataSource 继承 Observable,是具体的被观察者。通过 notifyObservers() 方法传递具体数据来实现通知所有观察者,传递的具体逻辑是在父类中实现的。
  3. 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 specialized to maintain  a registry of observers of specific types 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 will never be null.     /    protected final ArrayList<T> mObservers = new ArrayList<T>();    /      Adds an observer to the list. The observer cannot be null 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 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();        }    }}
  1. RecyclerView 静态内部类 AdapterDataObservable 是具体被观察者,Observable 类是 笼统被观察者,他们管理着具体观察者
  2. Adapter 中持有具体被观察者实例 mObservable
  3. 我们调使用 notifyDataSetChanged() 实际调使用了 具体被观察者实例 mObservablenotifyChanged() 方法。

那么接下来分析一下 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() 申请重新布局,至于怎么实现,感兴趣的同学能参考我另一篇文章:

Android View:一条线了解 View 绘制流程

那么回到正题,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();}

上面的代码主要关注的是下面两点:

  1. 第一个 if 中假如 mAdapter 不为 null,也就是重新设置 RecyclerView 的 adapter 时先解除旧的观察者对象。
  2. 为新的 adapter 注册观察者。
  3. 注意这里传递的参数 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。

  1. 首先是笼统主题,被观察者笼统:
//被观察者(一个笼统类,方便扩展)public abstract class Observable{     public final ArrayList<Class<?>> obserList = new ArrayList<Class<?>>();     /AttachObserver(通过实例注册观察者)    <b>Notice:</b>obcantbenull,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():通知所有观察者的函数,能自己实现来统一管理,也能交给子类去实现。这里是笼统方法,由子类实现。
  1. 笼统观察者,定义升级方法
//观察者,需要使用到观察者模式的类需实现此接口public interface Observer{    void update(Object...objs);}
  1. 具体被观察者,继承 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.getdMethods();        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 反射机制调使用具体观察中类的方法。
  1. 具体观察者类,需要增加到笼统被观察者维护的列表中。
//用(实现Observer接口)public class Text extends Activity implements Observer{    publicvoidonCreate(...){        ConcreteObservable.getInstance().registerObserver(Text.class);        ....    }     //实现接口解决    publicvoidupdate(Object...objs){        //做操作,比方升级数据,升级UI等    }}
六、总结

综上,只有找到四个重要角色:笼统观察者、具体观察者、笼统被观察者和具体观察者,以及三个方法:注册解除注册发送通知,即可以理清观察者模式的应使用了。

观察者模式的优点:

  • 解耦:
    观察者和被观察者之间建立的是一个笼统的耦合,被观察者并不需要理解每一个具体的观察者,但是能通过共同的接口来控制它们。
  • 扩展性高:
    假如需要创立新的观察者,只要要实现观察者笼统接口就可。

观察者模式的缺点:

  • 效率问题:
    假如观察者数量过多,遍历并按顺序执行它们的方法会产生效率问题。或者者某个观察者所执行的代码过于繁琐,影响其余观察者信息或者数据的接收。

有关观察者模式的记录就先到这里,在学会这些知识后灵活运使用才是最重要的。个人觉得没有最好的代码,只有最合适的代码。

参考资料:
《Android源码设计模式解析与实战》

网友评论