美文网首页
设计模式学习-观察者模式

设计模式学习-观察者模式

作者: m1Ku | 来源:发表于2018-12-02 10:41 被阅读0次

定义

定义对象之间一对多的依赖关系,使得每当一个对象发生变化时,则所有依赖于它的对象都会得到通知并自动更新。这个模式最重要的是可以做到被观察者和观察者的解耦,使他们的依赖性变小。而这个模式最常用于GUI系统以及订阅-发布系统,如期刊或者邮件的订阅等。

UML类图

观察者设计模式

观察者设计模式,主要有被观察者和观察者角色

  • Subject:

    抽象主题,是被观察者的角色。其有添加和删除观察者的方法,并且把观察者保存在一个集合中。

  • ConcreteSubject

    具体主题,抽象主题的实现类。定义通知观察者的方法,当其状态发生变化时,循环遍历观察者调用其update方法通知观察者更新。

  • Observer

    抽象观察者,定义了更新方法,得到被观察者变化的通知时更新自己。

  • ConcreteObserver

    具体的观察者,实现了具体的更新方法逻辑。

示例

当我们订阅了一种期刊,每当期刊更新时,发版商都会将最新的期刊邮寄给我们。这就是经典的发布订阅关系,即观察者设计模式。

/**
 * 期刊发布商角色
 * 即被观察者,当发布了新的期刊时通知订阅者
 */
public class Publisher extends Observable {
    //发布新期刊
    public void publishNew(String name){
        setChanged();
        notifyObservers(name);
    }
}

/**
 * 订阅者角色
 * 即观察者,收到更新
 */
public class Person implements Observer {
    private String name;
    public Person(String name){
        this.name = name;
    }

    @Override
    public void update(Observable o, Object arg) {
        System.out.println(name + "收到发布商的更新,内容为" + arg);
    }
}

  public static void main(String []args){
        Publisher publisher = new Publisher();
      
        publisher.addObserver(new Person("小明"));
        publisher.addObserver(new Person("小李"));
        publisher.addObserver(new Person("小王"));
        //发布更新
        publisher.publishNew("航空知识第12期发布");
    }
小王收到发布商的更新,内容为航空知识第12期发布
小李收到发布商的更新,内容为航空知识第12期发布
小明收到发布商的更新,内容为航空知识第12期发布

Android源码中的观察者模式

在使用ListView时,当数据源发生变化时,我们会调用adapter.notifyDataSetChanged()刷新列表,ListView就是使用了观察者设计模式。

首先看一下notifyDataSetChanged()的实现

public void notifyDataSetChanged() {
    mDataSetObservable.notifyChanged();
}

这里调用了mDataSetObservable的notifyChanged方法,而这个方法遍历了观察者对象,并调用了观察者的onChanged()方法,通知其发生了变化

public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * Invokes {@link DataSetObserver#onChanged} on each observer.
     * Called when the contents of the data set have changed.  The recipient
     * will obtain the new contents the next time it queries the data set.
     */
    public void notifyChanged() {
        synchronized(mObservers) {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
    //...
}

DataSetObservable是一个数据集的被观察者,定义在BaseAdapter中

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    private final DataSetObservable mDataSetObservable = new DataSetObservable();
    ...
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }
    
    /**
     * Notifies the attached observers that the underlying data has been changed
     * and any View reflecting the data set should refresh itself.
     */
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

    /**
     * Notifies the attached observers that the underlying data is no longer valid
     * or available. Once invoked this adapter is no longer valid and should
     * not report further data set changes.
     */
    public void notifyDataSetInvalidated() {
        mDataSetObservable.notifyInvalidated();
    }
    ...
}

BaseAdapter中有registerDataSetObserver方法接受一个DataSetObserver数据集观察者,并将其注册到DataSetObservable中,这样就形成了观察者和被观察者订阅关系。而这个方法在ListView的setAdapter方法中被调用并传入了AdapterDataSetObserver类型的观察者,如下

@Override
public void setAdapter(ListAdapter adapter) {
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }

    // AbsListView#setAdapter will update choice mode states.
    super.setAdapter(adapter);

    if (mAdapter != null) {
        mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
        mOldItemCount = mItemCount;
        mItemCount = mAdapter.getCount();
        checkFocus();

        mDataSetObserver = new AdapterDataSetObserver();
        mAdapter.registerDataSetObserver(mDataSetObserver);
        //...
    } else {
        //...
    }

    requestLayout();
}

这里实例化了一个AdapterDataSetObserver类型的观察者,其实现如下

class AdapterDataSetObserver extends DataSetObserver {

    private Parcelable mInstanceState = null;

    @Override
    public void onChanged() {
        mDataChanged = true;
        mOldItemCount = mItemCount;
        mItemCount = getAdapter().getCount();

        // Detect the case where a cursor that was previously invalidated has
        // been repopulated with new data.
        if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                && mOldItemCount == 0 && mItemCount > 0) {
            AdapterView.this.onRestoreInstanceState(mInstanceState);
            mInstanceState = null;
        } else {
            rememberSyncState();
        }
        checkFocus();
        requestLayout();
    }
    //...
}

在它的onChange方法中,最终调用了requestLayout()方法使ListView进行了重新布局。

相关文章

  • 设计模式之观察者模式

    设计模式之观察者模式 本篇是设计模式系列博客的第四篇,本篇主要学习设计模式中的第二个行为型模式---观察者模式。 ...

  • 观察者设计模式

    每周学点Java设计模式__观察者设计模式 本次继续更新java23中设计模式之一——观察者模式。 观察者模式(有...

  • iOS常用设计模式

    1.为什么学习设计模式 对于设计模式,我们并不陌生。一谈起设计模式,脑海里马上就想到单例模式,委托模式,观察者模式...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • 设计模式02-观察者者设计模式

    [toc] 设计模式02-观察者者设计模式 主要来源Head First设计模式(书)观察者设计模式是JDK中使用...

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • 设计模式之观察者设计模式

    最近补一下设计模式相关的知识,关于观察者设计模式主要从以下几个方面来学习,具体如下: 什么是观察者设计模式 关键概...

  • RxJava设计模式与原理

    标准观察者设计模式 RxJava是一种特殊的观察者模式,首先我们先来看标准的观察者设计模式。在标准观察者模式中,存...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • 设计模式之——观察者模式

    前言:本文仅作为第一次学习设计模式的参考和笔记。初探观察者模式: 观察者模式:Observer Pattern 又...

网友评论

      本文标题:设计模式学习-观察者模式

      本文链接:https://www.haomeiwen.com/subject/gqqjcqtx.html