前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >观察者模式

观察者模式

作者头像
提莫队长
发布2019-02-21 13:37:26
5520
发布2019-02-21 13:37:26
举报
文章被收录于专栏:刘晓杰刘晓杰

1.定义

观察者模式是一种行为类模式,它定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新。

2.实例(订阅杂志)

代码语言:javascript
复制
/**
 * 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己
 */
public interface Observer {
    /**
     * 有更新就推送消息
     */
    public void update(String message);
}

/**
 * 具体的观察者类,也就是订阅者
 */
public class User implements Observer {

    @Override
    public void update(String message) {
        System.out.println(name + "," + message + "更新了!");
    }

    // 订阅者的名字
    private String name;

    public User(String name) {
        this.name = name;
    }

}

/**
 * 抽象被观察者类
 */
public interface Observable {

    /**
     * 发送杂志
     */
    void sendMagazine(String message);

    /**
     * 添加用户
     */
    void addUser(Observer observer);
}

/**
 * 杂志社
 */
public class Magazine implements Observable {

    private ArrayList<Observer> mUserList = new ArrayList<Observer>();

    @Override
    public void sendMagazine(String message) {
        for(Observer observer : mUserList){
            observer.update(message);
        }
    }

    @Override
    public void addUser(Observer observer) {
        mUserList.add(observer);
    }

}

    public static void main(String[] args) {
        User user1 = new User("ez");
        User user2 = new User("111111");

        Magazine magazine = new Magazine();
        magazine.addUser(user1);
        magazine.addUser(user2);

        magazine.sendMagazine("杂志1");
        //ez,杂志1更新了!
        //111111,杂志1更新了!
    }

3.源码体现(BaseAdapter的notifyDataSetChanged)

代码语言:javascript
复制
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    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);
    }

    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();//********************跟踪这个
    }
    ......
}

public class DataSetObservable extends Observable<DataSetObserver> {
    public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }
}

mObservers从哪里来?下面的代码显示,是调用了registerObserver方法。该方法在BaseAdapter的registerDataSetObserver调用的

代码语言:javascript
复制
public abstract class Observable<T> {
    protected final ArrayList<T> mObservers = new ArrayList<T>();

    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);//**********************************
        }
    }
}

那么registerDataSetObserver又是什么时候调用的呢?下面的代码显示是ListView等控件setAdapter调用的

代码语言:javascript
复制
    @Override
    public void setAdapter(ListAdapter adapter) {
    ......
        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();

            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);//**************************在这里

            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());

            int position;
            if (mStackFromBottom) {
                position = lookForSelectablePosition(mItemCount - 1, false);
            } else {
                position = lookForSelectablePosition(0, true);
            }
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);

            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
        } else {
            mAreAllItemsSelectable = true;
            checkFocus();
            // Nothing selected
            checkSelectionChanged();
        }

        requestLayout();
    }

搞清楚了mObservers从哪里来,接下来就是要明白mObservers.get(i).onChanged();发生了啥?

代码语言:javascript
复制
public abstract class DataSetObserver {
    /**
     * This method is called when the entire data set has changed,
     * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
     */
    public void onChanged() {
        // Do nothing
    }
}

    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();//************************重新布局,ViewGroup
        }
    }

4.总结

1.优点 (1)观察者和被观察者之间是抽象耦合,应对业务变化。 (2)增强系统的灵活性和可扩展性。 2.缺点 在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年03月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.定义
  • 2.实例(订阅杂志)
  • 3.源码体现(BaseAdapter的notifyDataSetChanged)
  • 4.总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档