设计模式-观察者模式

来源:互联网 发布:淘宝客服如何算提成 编辑:程序博客网 时间: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()方法重新进行布局,更新用户的界面。这就是一个观察者模式!

1 0
原创粉丝点击