设计模式:观察者模式 源码分析和在 RecyclerView 中的体现

*本篇文章已授权微信公众号 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,这里写了两个。


    
  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 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();
    }
}

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

  1. 两个变量 changedobschanged 是数据是否变化的标记,主要作用是避免重复通知观察者。 obs 是一个自增长的数组,用来存放具体的观察者对象,也就是实现了 Observer 的实现类。
    这里有一个知识点:设计模式的 依赖倒置原则:面向接口编程而不是面向具体对象编程 。这个 obs 数组存放的是接口类型而不是某个具体实现类型表明了这一点。
  2. 添加和删除观察者对象的方法就是往数组 obs 添加和删除元素。
  3. 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(抽象被观察者) 已经分析的差不多了,那么再结合刚才的例子来总结一下:

  1. MyTextView 实现 Observer,是具体的观察者。实现方法 update() 来执行具体的逻辑。
  2. DataSource 继承 Observable,是具体的被观察者。通过 notifyObservers() 方法传递具体数据来实现通知所有观察者,传递的具体逻辑是在父类中实现的。
  3. Observable 作为抽象被观察者实现具体的数据传递逻辑,其内部维护了一个标记和具体观察者列表,当数据发生变化时遍历该列表并通过调用 update() 方法来通知具体观察者实现不同的逻辑。

四、观察者模式在 RecyclerView 中的体现

通过以上对观察者模式的了解,四个主要角色 抽象观察者、具体观察者、抽象被观察者和具体观察者 起到了重要作用,而他们的运作是通过三个重要方法 注册观察者、解除注册、发送通知 ,那么分析 RecyclerView 也要从这几点入手。

首先我们知道 RecyclerView 中使用了观察者模式(和 ListView 类似),也知道 notifyDataSetChanged() 起到通知界面刷新的功能,那么就从这个方法入手。

RecyclerView.Adapter # notifyDataSetChanged()
public abstract static class Adapter {
    private final RecyclerView.AdapterDataObservable mObservable = new RecyclerView.AdapterDataObservable();
    ...
    public final void notifyDataSetChanged() {
        mObservable.notifyChanged();
    }
    ...
}

这个方法其实是在 RecyclerView 的内部静态抽象类 Adapter 中,可以看到 notifyDataSetChanged() 实际调用了 Adapter 的成员变量 mObservable 的 notifyChanged() 方法,该方法的实现暂且不管。这个变量 mObservable 命名方式很熟悉,那么就去看一下这个 AdapterDataObservable 类吧。

static class AdapterDataObservable extends Observable

这个类继承了 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 {
    /**
     * The list of observers.  An observer can be in the list at most
     * once and will never be null.
     */
    protected final ArrayList mObservers = new ArrayList();

    /**
     * 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 mObservers = new ArrayList(); :根据这个 ArrayList 可以看出该类维护了一个类列表,那么这类应该就是 具体观察者 了。
  • registerObserver()unregisterObserver()unregisterAll() 符合抽象被观察者管理具体观察者的逻辑,所以这个类就是 抽象被观察者 角色了。

这样就可以确定刚才 RecyclerView.AdapterDataObservable 是一个 具体被观察者 了。理一下现在得到的逻辑:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 {
    // 为了方便理解我打乱了顺序,不要钻牛角尖
    // 1. AdapterDataObservable:具体被观察者   Observable:抽象被观察者
    static class AdapterDataObservable extends Observable {
        //3.mObservable.notifyChanged()
        public void notifyChanged() {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
    ...
    public abstract static class Adapter {
        //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 mObservers 的这个 就是 AdapterDataObserver。而这个 ArrayList 具体保存的是 AdapterDataObserver 的实现类 RecyclerViewDataObserver。

这一块我表达的可能不够清晰,那么这里的逻辑再理清一下:

在 setAdapter() 的过程中,将具体观察者类的实例 mObserver 作为参数传递,用于设置具体的观察者。然后

调用 Adapter 中的 registerAdapterDataObserver(AdapterDataObserver observer) 方法进行注册,因为 mObserver 是 AdapterDataObserver 的子类实例,所以可以接收。

接着再通过 Adapter 中的 具体被观察者实例 mObservable 调用父类 Observable 中的注册和解除注册方法处理逻辑。

到这里就差不多完成了整个过程:

  • 抽象被观察者:Observable
  • 具体被观察者: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(通过实例注册观察者)
    *Notice:obcan'tbenull,oritwillthrowNullPointerException
    **/
    public 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(注销观察者)
    *Notice:
    *ItreverseswithattachObserver()method
    **/
    publicvoid unRegisterObserver(Tob){
        if(ob==null) throw new NullPointerException();
        this.unRegisterObserver(ob.getClass());
    }
 
    /**UnattachObserver(注销观察者,有时候在未获取到实例使用)
    *Notice:
    *ItreverseswithattachObserver()method
    **/
    public void unRegisterObserver(Classcls){
        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 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  void notifyObserver(T t, Object... objs){
        if(t == null) throw new NullPointerException();
        this.notifyObserver(t.getClass(), objs);
    }
 
    @Override
    public void notifyObservers(Object... objs){
        for(Classcls : obserList){
            this.notifyObserver(cls, objs);
        }
    }
 
    //通过java反射机制实现调用
    @Override
    public void notifyObserver(Classcls, 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 反射机制调用具体观察中类的方法。
  1. 具体观察者类,需要添加到抽象被观察者维护的列表中。
//使用(实现Observer接口)
public class Text extends Activity implements Observer{
    publicvoidonCreate(...){
        ConcreteObservable.getInstance().registerObserver(Text.class);
        ....
    }
 
    //实现接口处理
    publicvoidupdate(Object...objs){
        //做操作,比如更新数据,更新UI等
    }
}

六、总结

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

观察者模式的优点:

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

观察者模式的缺点:

  • 效率问题:

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

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

参考资料:

《Android源码设计模式解析与实战》

简书责编内容来自:简书 (源链) | 更多关于

阅读提示:酷辣虫无法对本内容的真实性提供任何保证,请自行验证并承担相关的风险与后果!
本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 移动开发 » 设计模式:观察者模式 源码分析和在 RecyclerView 中的体现

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录