当前位置:   article > 正文

Android设计模式—观察者模式_registeradapterdataobserver

registeradapterdataobserver

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

观察者模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得他们之间的依赖性更小,甚至做到毫无依赖。

观察者模式使用场景:
①当一个对象的数据更新时需要通知其他对象,但这个对象又不希望和被通知的那些对象形成紧耦合。
②当一个对象的数据更新时,这个对象需要让其他对象也各自更新自己的数据,但这个对象不知道具体有多少对象需要更新数据。
③跨系统的消息交换场景,如消息队列、事件总线的处理机制。

观察者模式的UML图:
在这里插入图片描述
观察者模式中包含四种角色:
①Subject抽象主题/被观察者:抽象主题把所有观察者对象的引用保存到一个集合里,每个主题都可以有任何数量的观察者。该接口规定了具体主题需要实现的方法,一般有添加、删除和更新内容等基本方法。
②Observer抽象观察者:为所有的具体观察者定义一个统一的更新接口,使得在收到主题的更新通知时进行更新。
③ConcreteSubject具体主题/被观察者:包含经常发生变化的数据,将主题的有关状态存入具体观察者对象,在具体主题的内部状态发生改变时给所有注册过的观察者发出通知。
④ConcreteObserver具体观察者:实现抽象观察者定义的更新接口,在得知主题更改通知时更新自身的状态。

观察者模式的优点:
①解除观察者和主题之间的耦合,让耦合的双方都依赖于抽象,而不是依赖于具体,从而使各自的变化不会影响另一边的变化。
具体主题和具体观察者是松耦合关系。由于主题接口仅仅依赖于观察者接口,因此具体主题只是知道它的观察者是实现观察者接口的某个类的实例,但不需要知道具体是哪个类。同样由于观察者仅仅依赖于主题接口,因此具体观察者只知道它依赖的主题是实现主题接口的某个类的实例,但不需要知道具体是哪个类。
②满足设计模式中的“开-闭原则”,易于扩展。对于同一主题新增观察者时无需修改原有代码。
主题接口仅仅依赖于观察者接口,这样就可以让创建具体主题的类也仅仅是依赖于观察者接口,因此如果增加新的观察者类,不必修改创建具体主题的类的代码。同样创建具体观察者的类仅仅依赖于主题接口,如果增加新的主题接口类,也不必修改创建具体观察者类的代码。

观察者模式的缺点:
①依赖关系并未完全解除,抽象主题仍然依赖抽象观察者。
②程序中包含一个被观察者、多个观察者,开发、调试会比较复杂。

2.观察者模式举例
①抽象被观察者
public interface Subject {
void registerObserver(Observer o);//增加观察者
void removeObserver(Observer o);//移除观察者
void notifyObservers(float temprature);//通知观察者去更新
}
②抽象观察者
public interface Observer {
void update(float temprature);//收到通知开始更新
void remove(Subject mSubject);//不想再观察的时候删除
}
③具体被观察者
public class ConcreteSubject implements Subject {
private List observers = new ArrayList<>();
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
@Override
public void removeObserver(Observer o) {
if (observers.indexOf(o) >= 0) {
observers.remove(o);
}
}
@Override
public void notifyObservers(float temprature) {
if (observers.size() <= 0) {
System.out.println(“没有观察者”);
return;
}
for (final Observer o : observers) {
o.update(temprature);//循环调用每个观察者的更新方法,让所有观察者去更新
}
}
}
实现了主题的所有接口,可以添加、删除和通知所有的观察者。
④具体观察者
public class ConcreteObserver implements Observer {
@Override
public void update(float temprature) { //主题调用更新方法时,会调用每个观察者的这个方法,让观察者更新数据
Log.e(TAG, “温度为:” + temprature);
}
@Override
public void remove(Subject mSubject) {
mSubject.removeObserver(this);//不需要观察时调用主题的删除方法,删掉该观察者
}
}
⑤客户端
public static void main(String[] args){
Subject sb = new ConcreteSubject();
Observer observer = new ConcreteObserver();
sb.registerObserver(observer);
sb.notifyObservers(21.0f);
observer.remove(sb);
sb.notifyObservers(23.0f);
}
先注册一个具体的观察者,然后主题发布一个温度,具体的观察者就收到通知了,而当具体的观察者删掉了主题之后就再也收不到通知了。

这只是一个主题和一个抽象观察者,实际上不管多少个主题或抽象观察者,都是一样的,基本原理都是"订阅-发布-更新"系统。

3.观察者模式在Android源码中的应用
在使用Listview时,如果数据改变了需要调用notifyDataSetChanged()方法来通知ListView更新UI。这里ListView的UI是观察者,ListView对应的adapter中的数据就是被观察者,它的实现方式就是注册一个观察者到adapter中,以实现监听adapter中数据变化的目的。

首先看ListView的setAdapter()方法:
public void setAdapter(ListAdapter adapter) {
//判断之前是否注册过观察者,如果注册过先注销,避免多次注册
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver( mDataSetObserver);
}

if (mAdapter != null) {

mDataSetObserver = new AdapterDataSetObserver(); //创建观察者
mAdapter.registerDataSetObserver( mDataSetObserver); //将观察者注册到adapter

}

}
在setAdapter()方法中,ListView会创建一个
AdapterDataSetObserver类的观察者,并且调用adapter的registerDataSetObserver()将这个观察者注册。

继续看Adapter的registerDataSetObserver方法:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable(); //被观察者
public void registerDataSetObserver( DataSetObserver observer) {
mDataSetObservable.registerObserver( observer);
}
public void unregisterDataSetObserver( DataSetObserver observer) {
mDataSetObservable.unregisterObserver( observer);
}

}
最终把观察者注册到DataSetObservable这个发布者里。

在被观察者中添加好了观察者,现在来看一下更新方法,即adapter.notifyDataSetChanged():
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged();
}
}
DataSetObservable是具体被观察者,看一下它的notifyChanged()方法:
public class DataSetObservable extends Observable {
public void notifyChanged() {
synchronized(mObservers) {
//通知所有的观察者调用onChanged
for (int i = mObservers.size() - 1; i >= 0; i–) {
mObservers.get(i).onChanged();
}
}
}
}
其实就是调用被观察者的notifyChanged()通知观察者调用onChanged刷新UI界面。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/286303
推荐阅读
相关标签
  

闽ICP备14008679号