设计模式之观察者模式源码分析及实践

640?wx_fmt=png&wxfrom=5&wx_lazy=1


今日科技快讯


4月27日,滴滴出行与国际金融公司(IFC)签署合作谅解备忘录,将在新兴市场中开启女性发展、数字普惠金融、绿色金融及跨国合作等领域的合作。滴滴表示,在这一合作框架下,双方将探索利用数字技术实现赋能女性乘客、司机、女性中小型企业主及女性员工。


作者简介


咦!今天好像是周六哦!接下来的三天就不再发文章了,这里提前祝大家五一节快乐!

本篇来自 Marker_Sky 的投稿,分享了观察者模式 源码分析和在 RecyclerView 中的体现,一起来看看!希望大家喜欢。

Marker_Sky  的博客地址:

https://www.jianshu.com/u/d46b4a47db84


前言


扫描二维码关注公众号,回复: 165297 查看本文章

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


正文


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

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

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

解耦的好处不用多说,设计模式中 单一职责原则 也表明我们希望每个实体(类、函数、模块等)能引起其改变的原因只有它自己。

也就是说,我们希望观察者的逻辑和被观察者的逻辑是分离的。

使用场景

  • 某些时候需要一些对象有所关联,而且这种关联是可以拆分而不是组合在一起的。

  • 某一事件发生,需要向多方触发。

  • 消息交换,如消息队列、事件总线的处理机制。

UML类图

640?wx_fmt=png

观察者模式主要角色

  • 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 的数据都发生了变化。

640?wx_fmt=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();
       }
       // 遍历所有观察者并调用其 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 添加和删除元素。

  • notifyObservers() 通知所有观察者,可以看到该函数使用了 synchronized 保证线程安全,然后 hasChanged() 获取当前标记状态,如果标记为 false 则 return 不进行通知。

  • 那么这个标记什么时候才能为 true 呢?是在该类的子类中,也就是刚才例子中 DataSource 数据源类 updateData() 方法中首先调用 setChanged() 来设置标记为 true,表明数据即将进行更新。

  • 之后将数组 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() 申请重新布局,至于怎样实现,感兴趣的同学可以参考我另一篇文章:

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

https://www.jianshu.com/p/e9ce78a01a93

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


总结


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

观察者模式的优点

  • 解耦

    • 观察者和被观察者之间建立的是一个抽象的耦合,被观察者并不需要了解每一个具体的观察者,但是可以通过共同的接口来控制它们。

  • 扩展性高

    • 如果需要创建新的观察者,只需要实现观察者抽象接口即可。

观察者模式的缺点

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

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


欢迎长按下图 -> 识别图中二维码

或者 扫一扫 关注我的公众号

640.png?

640?wx_fmt=jpeg

猜你喜欢

转载自blog.csdn.net/c10wtiybq1ye3/article/details/80117154