设计模式观察者模式

作者: GB_speak | 来源:发表于2017-04-13 15:14 被阅读24次

1.观察者模式的定义及使用场景
观察者模式是一个使用率非常高的模式,它最常用的地方是GUI系统,订阅-发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小。
定义:
定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所以依赖于它的对象都会得到通知并被自动更新
使用场景:
关联行为场景,需要注意的是,关联行为时可拆分的,而不是“组合”关系;
事件多级触发场景
跨系统的消息交换场景,如消息队列、事件总线的处理机制

Paste_Image.png
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()方法重新进行布局,更新用户的界面。这就是一个观察者模式!
出处:http://huangjunbin.com/page/2/

相关文章

  • 观察者设计模式

    每周学点Java设计模式__观察者设计模式 本次继续更新java23中设计模式之一——观察者模式。 观察者模式(有...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • 设计模式02-观察者者设计模式

    [toc] 设计模式02-观察者者设计模式 主要来源Head First设计模式(书)观察者设计模式是JDK中使用...

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • RxJava设计模式与原理

    标准观察者设计模式 RxJava是一种特殊的观察者模式,首先我们先来看标准的观察者设计模式。在标准观察者模式中,存...

  • 设计模式

    常用的设计模式有,单例设计模式、观察者设计模式、工厂设计模式、装饰设计模式、代理设计模式,模板设计模式等等。 单例...

  • Guava源码分析——EventBus

    EventBus的设计理念是基于观察者模式的,可以参考设计模式(1)—观察者模式先来了解该设计模式。 1、程序示例...

  • 设计模式之观察者模式

    设计模式之观察者模式 本篇是设计模式系列博客的第四篇,本篇主要学习设计模式中的第二个行为型模式---观察者模式。 ...

  • PHP设计模式之观察者模式

    PHP设计模式之观察者模式

  • Android中涉及的模式

    我的Java设计模式-建造者模式 我的Java设计模式-观察者模式 重学设计模式之单例模式

网友评论

    本文标题:设计模式观察者模式

    本文链接:https://www.haomeiwen.com/subject/gxvbattx.html