观察者模式

2019-02-21 13:37:26 浏览数 (1)

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中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

0 人点赞