设计模式之---观察者模式简单分析

来源:互联网 发布:全国省份数据库 编辑:程序博客网 时间:2024/06/05 07:13

    • 定义
    • 使用场景
    • 实例
    • 源码分析
    • Android源码中观察者

定义

观察者模式是一个使用率非常高的模式,他的一个重要作用就是用来解耦。它是一种一对多的依赖关系,当被观察者发生改变,所以的观察者都会收到通知

使用场景

有很多,如事件多级触发场景,关联行为场景,夸系统的消息交换场景,如消息队列,时间总线的处理机制

实例

/** * Created by zxa on 2017/3/21. * 观察者 */public class Visitor implements Observer{    public String name ;    @Override    public String toString() {        return "AdWall{" +                "name='" + name + '\'' +                '}';    }    public Visitor(String name) {        this.name = name;    }    @Override    public void update(Observable o, Object arg) {        Log.i("Visitor",o.toString()+"--"+name + ":广告墙 ,更新内容了,内容:" + arg);    }}/** * Created by zxa on 2017/3/21. * 这个类是被观察者的角色,相当于广告墙 */public class AdvWall extends Observable {    @Override    public String    toString() {        return  "AdvWall='" + boss;    }    public String boss = "boss说:";    public AdvWall() {    }    public void publicationNews(String content){        setChanged();        notifyObservers(content);    }}public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        AdvWall advWall = new AdvWall();        Visitor v_1 = new Visitor("visitor_1");        Visitor v_2 = new Visitor("visitor_2");        Visitor v_3 = new Visitor("visitor_3");        Visitor v_4 = new Visitor("visitor_4");        Visitor v_5 = new Visitor("visitor_5");        advWall.addObserver(v_1);        advWall.addObserver(v_2);        advWall.addObserver(v_3);        advWall.addObserver(v_4);        advWall.addObserver(v_5);        advWall.publicationNews("广告墙更新了,新的职位出来了,赶紧投简历-----手慢无");    }}

运行结果如下:
03-21 11:44:21.903 17004-17004/com.example.zxa.myapplication I/coder: hi,o:AdvWall{boss=’boss说:’}–visitor_1:广告墙 ,更新内容了,内容:广告墙更新了,新的职位出来了,赶紧投简历—–手慢无
03-21 11:44:21.903 17004-17004/com.example.zxa.myapplication I/coder: hi,o:AdvWall{boss=’boss说:’}–visitor_2:广告墙 ,更新内容了,内容:广告墙更新了,新的职位出来了,赶紧投简历—–手慢无
03-21 11:44:21.903 17004-17004/com.example.zxa.myapplication I/coder: hi,o:AdvWall{boss=’boss说:’}–visitor_3:广告墙 ,更新内容了,内容:广告墙更新了,新的职位出来了,赶紧投简历—–手慢无
03-21 11:44:21.903 17004-17004/com.example.zxa.myapplication I/coder: hi,o:AdvWall{boss=’boss说:’}–visitor_4:广告墙 ,更新内容了,内容:广告墙更新了,新的职位出来了,赶紧投简历—–手慢无
03-21 11:44:21.903 17004-17004/com.example.zxa.myapplication I/coder: hi,o:AdvWall{boss=’boss说:’}–visitor_5:广告墙 ,更新内容了,内容:广告墙更新了,新的职位出来了,赶紧投简历—–手慢无

源码分析

Observer是一个接口只有一个抽象方法void update(Observable o, Object arg);
下面的注释大体上说:
一个类想成为观察者希望被通知,就要实现

/** * A class can implement the <code>Observer</code> interface when it * wants to be informed of changes in observable objects. * * @author  Chris Warth * @see     java.util.Observable * @since   JDK1.0 */public interface Observer {    /**     * This method is called whenever the observed object is changed. An     * application calls an <tt>Observable</tt> object's     * <code>notifyObservers</code> method to have all the object's     * observers notified of the change.     *     * @param   o     the observable object.     * @param   arg   an argument passed to the <code>notifyObservers</code>     *                 method.     */    void update(Observable o, Object arg);}

Observable中保存了一个observers = new ArrayList<>();集合,用来保存观察者对象
setChanged clearChanged分别用来设置标志位

  /**     * Marks this <tt>Observable</tt> object as having been changed; the     * <tt>hasChanged</tt> method will now return <tt>true</tt>.     */    protected synchronized void setChanged() {        changed = true;    }    /**     * Indicates that this object has no longer changed, or that it has     * already notified all of its observers of its most recent change,     * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.     * This method is called automatically by the     * <code>notifyObservers</code> methods.     *     * @see     java.util.Observable#notifyObservers()     * @see     java.util.Observable#notifyObservers(java.lang.Object)     */    protected synchronized void clearChanged() {        changed = false;    }

notifyObservers用来通知各个观察者有新的内容更新,最主要通过changed这个标志位来标记。

   /**     * If this object has changed, as indicated by the     * <code>hasChanged</code> method, then notify all of its observers     * and then call the <code>clearChanged</code> method to indicate     * that this object has no longer changed.     * <p>     * Each observer has its <code>update</code> method called with two     * arguments: this observable object and the <code>arg</code> argument.     *     * @param   arg   any object.     * @see     java.util.Observable#clearChanged()     * @see     java.util.Observable#hasChanged()     * @see     java.util.Observer#update(java.util.Observable, java.lang.Object)     */    public void notifyObservers(Object arg) {        /*         * a temporary array buffer, used as a snapshot of the state of         * current Observers.         */        Observer[] arrLocal;        synchronized (this) {            /* We don't want the Observer doing callbacks into             * arbitrary Observables while holding its own Monitor.             * The code where we extract each Observable from             * the ArrayList and store the state of the Observer             * needs synchronization, but notifying observers             * does not (should not).  The worst result of any             * potential race-condition here is that:             *             * 1) a newly-added Observer will miss a             *   notification in progress             * 2) a recently unregistered Observer will be             *   wrongly notified when it doesn't care             */            if (!hasChanged())                return;            arrLocal = observers.toArray(new Observer[observers.size()]);            clearChanged();        }        for (int i = arrLocal.length-1; i>=0; i--)            arrLocal[i].update(this, arg);    }

Android源码中观察者

BaseAdapter中就有个被观察者如下:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {    // 这里相当于上面的AdvWall类    private final DataSetObservable mDataSetObservable = new DataSetObservable();    public boolean hasStableIds() {        return false;    }    public void registerDataSetObserver(DataSetObserver observer) {        mDataSetObservable.registerObserver(observer);    }    public void unregisterDataSetObserver(DataSetObserver observer) {        mDataSetObservable.unregisterObserver(observer);    }

那观察者在哪里呢? 我们看下

   @Override    public void setAdapter(ListAdapter adapter) {        if (mAdapter != null && mDataSetObserver != null) {           //这里解注册            mAdapter.unregisterDataSetObserver(mDataSetObserver);        }        resetList();        mRecycler.clear();        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {            mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);        } else {            mAdapter = adapter;        }        mOldSelectedPosition = INVALID_POSITION;        mOldSelectedRowId = INVALID_ROW_ID;        // AbsListView#setAdapter will update choice mode states.        super.setAdapter(adapter);        if (mAdapter != null) {            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();            mOldItemCount = mItemCount;            mItemCount = mAdapter.getCount();            checkFocus();            //这里new了一个观察者 并且注册            mDataSetObserver = new AdapterDataSetObserver();            mAdapter.registerDataSetObserver(mDataSetObserver);            --------}

下面看下AdapterDataSetObserver的实现

    class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {        @Override        public void onChanged() {            super.onChanged();            if (mFastScroll != null) {                mFastScroll.onSectionsChanged();            }        }        @Override        public void onInvalidated() {            super.onInvalidated();            if (mFastScroll != null) {                mFastScroll.onSectionsChanged();            }        }    }

其中AdapterDataSetObserver中的onChanged()的实现如下

   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(); //这句话比较关键,是重新测量布局        }

综上所述,观察者在实际的开发中运用的非常的多,希望大家理解并熟练运用

注:本文参考 【Android源码设计模式】

0 0