观察者模式

    xiaoxiao2021-03-25  71

    1.定义

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

    2.实例(订阅杂志)

    /** * 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己 */ 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)

    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调用的

    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调用的

    @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();发生了啥?

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

    转载请注明原文地址: https://ju.6miu.com/read-37533.html

    最新回复(0)