观察者模式
观察者模式是使用率非常高的一种设计模式。
什么是观察模式?
对象间存在一对多的依赖关系,需要在某个对象改变的时候,依赖于该对象的所有其他对象都收到通知并进行更新和相应的业务操作。
简而言之,就是当一个被观察的对象改变了就要去通知它的观察者,告诉观察者我有变化了,你可以进行你需要的处理操作。
无处不在的观察者
情景一:小明(观察者)给妈妈说饭熟了叫我吃饭,妈妈(被观察者)等到饭熟了就会通知小明来吃饭了。
情景二:代码中有个需求需要监听用户打开蓝牙就关掉蓝牙。这肯定需要使用观察者模式,监听到蓝牙打开了,就通知相应的观察者,然后做关掉蓝牙的操作。
观察者模式的作用就是使对象解耦,将观察者和被观察者完全隔离。上述情景,小明可以在妈妈做饭的时候写作业,等妈妈叫她吃饭的时候再去吃饭。这样小明和妈妈就可以各干各的事情,完全解耦。
最简单的观察者模式Demo
项目结构如下,只有4个类超级简单。
- 被观察接口,三个方法,注册监听者,注销监听者,通知所有观察者
/**
* 被观察者接口
*/
public interface IObservable {
void registerObserver(IObserver observer);
void unregisterObserver(IObserver observer);
void notifyAllObservers();
}
- 观察者接口:更新数据
/**
* 观察者接口
*/
public interface IObserver {
void update();
}
- 观察者实现类
/**
* 观察者实现类
*/
public class ObserverImpl implements IObserver{
private static final String TAG = "ObserverImpl";
private String observerName;
public ObserverImpl(String observerName){
this.observerName = observerName;
}
@Override
public void update() {
Log.i(TAG,observerName +"数据更新了----->");
}
}
- 被观察者实现类
/**
* 被观察者实现类
*/
public class ObservableImpl implements IObservable{
private List<IObserver> mObserversList = new ArrayList<>();//注册的所有观察者集合
@Override
public void registerObserver(IObserver observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObserversList) {
if (mObserversList.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObserversList.add(observer);
}
}
@Override
public void unregisterObserver(IObserver observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(observer) {
int index = mObserversList.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObserversList.remove(index);
}
}
@Override
public void notifyAllObservers() {
for(int i = 0;i < mObserversList.size(); i++){
IObserver observer = mObserversList.get(i);
observer.update();
}
}
}
其实看了被观察者的实现,原来所谓的注册监听和取消监听都是靠一个list集合来维护,最后的通知观察者的本质也就是遍历这个list集合,然后调用观察者的update方法。
- 测试demo
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ObserverImpl observer1 = new ObserverImpl("观察者 1 :");
ObserverImpl observer2 = new ObserverImpl("观察者 2 :");
ObservableImpl observable = new ObservableImpl();//被观察者
observable.registerObserver(observer1);
observable.registerObserver(observer2);
// observable.unregisterObserver(observer2);
observable.notifyAllObservers();
}
}
- 测试结果:
我们可以从结果看出注册的2个观察者都收到数据更新的消息了。这就是目前演示的最简单的观察者模式的写法。
观察者模式在Android源码中的使用:
- 四大组件其中一个:Broadcast其实就是一个订阅发布的观察者模式。我们注册广播接收者registerReceiver,当sendBroadcast的发送广播时,onReceive 方法就会被调用。这是一个非常典型的观察者模式。onReceive方法就类似于上述例子中的观察者接口中的update()方法。细细想来,其实我们见过的很多代码其实使用的就是观察者模式。
-其实ListView使用Adapter模式也是观察者模式
我们在使用ListView的时候会使用到一个方法notifyDataSetChanged();每当有数据源更新,调用该方法就可以更新页面。notifyDataSetChanged()源码其实和上述的被观察者实现类里面 notifyAllObservers()的方法类似。
Android源码其实就是一个很好的学习的例子,我们平时使用的很多模式在源码中都有体现。观察者模式是我们必现要掌握的设计模式之一。