设计模式-观察者模式
来源:互联网 发布:淘宝客服如何算提成 编辑:程序博客网 时间:2024/06/03 12:32
1.观察者模式的定义及使用场景
观察者模式是一个使用率非常高的模式,它最常用的地方是GUI系统,订阅-发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小。
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所以依赖于它的对象都会得到通知并被自动更新
使用场景:
- 关联行为场景,需要注意的是,关联行为时可拆分的,而不是“组合”关系;
- 事件多级触发场景
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制
2. 观察者模式的优缺点
2.1优点
- 观察者和被观察者之间是抽象解耦,应对业务变化
- 增强系统灵活性、可扩展性
2.2缺点
在应用观察者模式时需要考虑一下开发效率和运行效率问题,程序中包括一个被观察者、多个观察者、开发和调试等内容会比较复杂,而且在Java中消息的通知默认是顺序执行,一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般考虑采用异步的方式
3. 观察者模式的实现方式
public interface Observer { //更新方法 public void update();}
public class ConcreteObsever implements Observer { @Override public void update() { System.out.println("接收到信息,并进行处理!"); }}
public abstract class Subject { //定义一个观察者数组 private List<Observer> observers = new ArrayList<>(); //增加一个观察者 public void addObserver(Observer o) { this.observers.add(o); } //删除一个观察者 public void removeObserver(Observer o) { this.observers.remove(o); } //通知所有观察者 public void notifyObservers() { for (Observer o : this.observers) { o.update(); } }}
public class ConcreteSubject extends Subject { //具体的业务 public void doSomeThing() { super.notifyObservers(); }}
public class Test { public static void main(String args[]) { //创建一个被观察者 ConcreteSubject subject=new ConcreteSubject(); Observer obs=new ConcreteObsever(); subject.addObserver(obs); subject.doSomeThing(); }}
4. 观察者模式在Android中的实际应用
RecycleView是Android中最重要的控件之一,而RecycleView最重要的一个功能就是Adapter。通过我们往RecycleView添加数据后,都会调用Adapter的notifyDataSetChanged()方法,这是为什么?
首先我们看下Adapter的实现,他是RecycleView的一个内部类。
public static abstract class Adapter<VH extends ViewHolder> { private final AdapterDataObservable mObservable = new AdapterDataObservable(); private boolean mHasStableIds = false; public abstract VH onCreateViewHolder(ViewGroup parent, int viewType); public abstract void onBindViewHolder(VH holder, int position); public void onBindViewHolder(VH holder, int position, List<Object> payloads) { onBindViewHolder(holder, position); } public final VH createViewHolder(ViewGroup parent, int viewType) { TraceCompat.beginSection(TRACE_CREATE_VIEW_TAG); final VH holder = onCreateViewHolder(parent, viewType); holder.mItemViewType = viewType; TraceCompat.endSection(); return holder; } public final void bindViewHolder(VH holder, int position) { holder.mPosition = position; if (hasStableIds()) { holder.mItemId = getItemId(position); } holder.setFlags(ViewHolder.FLAG_BOUND, ViewHolder.FLAG_BOUND | ViewHolder.FLAG_UPDATE | ViewHolder.FLAG_INVALID | ViewHolder.FLAG_ADAPTER_POSITION_UNKNOWN); TraceCompat.beginSection(TRACE_BIND_VIEW_TAG); onBindViewHolder(holder, position, holder.getUnmodifiedPayloads()); holder.clearPayload(); TraceCompat.endSection(); } public int getItemViewType(int position) { return 0; } public void setHasStableIds(boolean hasStableIds) { if (hasObservers()) { throw new IllegalStateException("Cannot change whether this adapter has " + "stable IDs while the adapter has registered observers."); } mHasStableIds = hasStableIds; } public long getItemId(int position) { return NO_ID; } public abstract int getItemCount(); public final boolean hasStableIds() { return mHasStableIds; } public void onViewRecycled(VH holder) { } public boolean onFailedToRecycleView(VH holder) { return false; } public void onViewAttachedToWindow(VH holder) { } public void onViewDetachedFromWindow(VH holder) { } public final boolean hasObservers() { return mObservable.hasObservers(); } public void registerAdapterDataObserver(AdapterDataObserver observer) { mObservable.registerObserver(observer); } public void unregisterAdapterDataObserver(AdapterDataObserver observer) { mObservable.unregisterObserver(observer); } public void onAttachedToRecyclerView(RecyclerView recyclerView) { } public void onDetachedFromRecyclerView(RecyclerView recyclerView) { } public final void notifyDataSetChanged() { mObservable.notifyChanged(); } public final void notifyItemChanged(int position) { mObservable.notifyItemRangeChanged(position, 1); } public final void notifyItemChanged(int position, Object payload) { mObservable.notifyItemRangeChanged(position, 1, payload); } public final void notifyItemRangeChanged(int positionStart, int itemCount) { mObservable.notifyItemRangeChanged(positionStart, itemCount); } public final void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) { mObservable.notifyItemRangeChanged(positionStart, itemCount, payload); } public final void notifyItemInserted(int position) { mObservable.notifyItemRangeInserted(position, 1); } public final void notifyItemMoved(int fromPosition, int toPosition) { mObservable.notifyItemMoved(fromPosition, toPosition); } public final void notifyItemRangeInserted(int positionStart, int itemCount) { mObservable.notifyItemRangeInserted(positionStart, itemCount); } public final void notifyItemRemoved(int position) { mObservable.notifyItemRangeRemoved(position, 1); } public final void notifyItemRangeRemoved(int positionStart, int itemCount) { mObservable.notifyItemRangeRemoved(positionStart, itemCount); } }
我们可以看到notifyDataSetChange()中调用了mObservable.notifyChange()。继续看AdapterDataObservable类
static class AdapterDataObservable extends Observable<AdapterDataObserver> { public boolean hasObservers() { return !mObservers.isEmpty(); } public void notifyChanged() { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } public void notifyItemRangeChanged(int positionStart, int itemCount) { notifyItemRangeChanged(positionStart, itemCount, null); } public void notifyItemRangeChanged(int positionStart, int itemCount, Object payload) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload); } } public void notifyItemRangeInserted(int positionStart, int itemCount) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeInserted(positionStart, itemCount); } } public void notifyItemRangeRemoved(int positionStart, int itemCount) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeRemoved(positionStart, itemCount); } } public void notifyItemMoved(int fromPosition, int toPosition) { for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1); } } }
Observable是一个被观察者:
public abstract class Observable<T> { /** * The list of observers. An observer can be in the list at most * once and will never be null. */ protected final ArrayList<T> mObservers = new ArrayList<T>(); /** * Adds an observer to the list. The observer cannot be null and it must not already * be registered. * @param observer the observer to register * @throws IllegalArgumentException the observer is null * @throws IllegalStateException the observer is already registered */ 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); } } /** * Removes a previously registered observer. The observer must not be null and it * must already have been registered. * @param observer the observer to unregister * @throws IllegalArgumentException the observer is null * @throws IllegalStateException the observer is not yet registered */ public void unregisterObserver(T observer) { if (observer == null) { throw new IllegalArgumentException("The observer is null."); } synchronized(mObservers) { int index = mObservers.indexOf(observer); if (index == -1) { throw new IllegalStateException("Observer " + observer + " was not registered."); } mObservers.remove(index); } } /** * Remove all registered observers. */ public void unregisterAll() { synchronized(mObservers) { mObservers.clear(); } }}
AdapterDataObserver 的派生类RecyclerViewDataObserver: mObserver是RecycleView的一个变量
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
private class RecyclerViewDataObserver extends AdapterDataObserver { @Override public void onChanged() { assertNotInLayoutOrScroll(null); if (mAdapter.hasStableIds()) { // TODO Determine what actually changed. // This is more important to implement now since this callback will disable all // animations because we cannot rely on positions. mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } else { mState.mStructureChanged = true; setDataSetChangedAfterLayout(); } if (!mAdapterHelper.hasPendingUpdates()) { requestLayout(); } } @Override public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) { triggerUpdateProcessor(); } } @Override public void onItemRangeInserted(int positionStart, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) { triggerUpdateProcessor(); } } @Override public void onItemRangeRemoved(int positionStart, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) { triggerUpdateProcessor(); } } @Override public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { assertNotInLayoutOrScroll(null); if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) { triggerUpdateProcessor(); } } void triggerUpdateProcessor() { if (mPostUpdatesOnAnimation && mHasFixedSize && mIsAttached) { ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable); } else { mAdapterUpdateDuringMeasure = true; requestLayout(); } } }
RecycleView的setAdapter方法,可以看到里面调用了unregisterAdapterDataObserver及registerAdapterDataObserver方法进行取消注册及注册。
public void setAdapter(Adapter adapter) { // bail out if layout is frozen setLayoutFrozen(false); setAdapterInternal(adapter, false, true); requestLayout(); } private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious, boolean removeAndRecycleViews) { if (mAdapter != null) { mAdapter.unregisterAdapterDataObserver(mObserver); mAdapter.onDetachedFromRecyclerView(this); } if (!compatibleWithPrevious || removeAndRecycleViews) { // end all running animations if (mItemAnimator != null) { mItemAnimator.endAnimations(); } // Since animations are ended, mLayout.children should be equal to // recyclerView.children. This may not be true if item animator's end does not work as // expected. (e.g. not release children instantly). It is safer to use mLayout's child // count. if (mLayout != null) { mLayout.removeAndRecycleAllViews(mRecycler); mLayout.removeAndRecycleScrapInt(mRecycler); } // we should clear it here before adapters are swapped to ensure correct callbacks. mRecycler.clear(); } mAdapterHelper.reset(); final Adapter oldAdapter = mAdapter; mAdapter = adapter; if (adapter != null) { adapter.registerAdapterDataObserver(mObserver); adapter.onAttachedToRecyclerView(this); } if (mLayout != null) { mLayout.onAdapterChanged(oldAdapter, mAdapter); } mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious); mState.mStructureChanged = true; markKnownViewsInvalid(); }
到这里我们知道,setAdapter()方法会进行观察者的注册,当RecycleView的数据发送变化的时,调用了Adapter的notifyDataSetChange(),这个函数又会调用 AdapterDataObservable的notifyChanged();该函数会遍历所有的观察者的onChange函数,在 RecyclerViewDataObserver的onChange()函数中会获取Adapter中数据集的新数量,然后调用RecycleView的requestLayout()方法重新进行布局,更新用户的界面。这就是一个观察者模式!
- 模式设计:观察者模式
- 设计模式-----观察者模式
- 设计模式-观察者模式
- 设计模式--观察者模式
- 设计模式:观察者模式
- 设计模式-----观察者模式
- 设计模式:观察者模式
- 设计模式-观察者模式
- 设计模式 观察者模式
- 设计模式-观察者模式
- 设计模式-【观察者模式】
- 设计模式-观察者模式
- 设计模式 -- 观察者模式
- 设计模式-观察者模式
- 【设计模式】观察者模式
- 设计模式- 观察者模式
- 设计模式- 观察者模式
- 设计模式--观察者模式
- Hibernate一对多关系详解
- javaScript数组方法
- Mybatis学习【1】
- 体验Ipython 惹得祸
- ORTC以及WebRTC的未来【转】
- 设计模式-观察者模式
- java.lang.IllegalArgumentException: Malformed /uxxxx encoding
- CentOS7安装MongoDB3.4(yum安装)
- HttpURLConnection用法详解
- 《cuda并行程序设计》勘误(2)
- Redis相关教程收集
- 部署Zipkin分布式性能追踪日志系统的操作记录
- 构造函数和析构函数
- 02-HDFS的原理和使用操作、编程