概述:
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时, 所有依赖于它的对象都得到通知并被自动更新。
解决的问题
将一个系统分割成一个一些类相互协作的类有一个不好的副作用,那就是需要维护相关对象间的一致性。我们不希望为了维持一致性而使各类紧密耦合,这样会给维护、扩展和重用都带来不便。观察者就是解决这类的耦合关系的。
模式中的角色
- 抽象主题(Subject):它把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。
- 具体主题(ConcreteSubject):将有关状态存入具体观察者对象;在具体主题内部状态改变时,给所有登记过的观察者发出通知。
- 抽象观察者(Observer):为所有的具体观察者定义一个接口,在得到主题通知时更新自己。
- 具体观察者(ConcreteObserver):实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题状态协调。
代码实现(Java)
package com.mode.observer;
import java.util.ArrayList;
/**
* 观察者操作类
*/
public abstract class Observable<T> {
protected final ArrayList<T> mObservers = new ArrayList<T>();
/**
* 添加观察者
*/
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);
}
}
/**
* 删除某个观察者
*/
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);
}
}
/**
* 移除全部观察者
*/
public void unregisterAll() {
synchronized (mObservers) {
mObservers.clear();
}
}
}
package com.mode.observer;
/**
* 观察者通知方法接口
*/
public abstract class DataSetObserver {
public abstract void onChanged();
}
package com.mode.observer;
/**
* 通知观察者类
*/
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* 数据发生变化时,通知所有的观察者
*/
public void notifyChanged() {
synchronized (mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onChanged();
}
}
}
}
调用:
package com.mode.observer;
public class ObTest {
// 观察者类
public static DataSetObservable mDataSetObservable = new DataSetObservable();
// 观察者模式
static class NewDataObServer extends DataSetObserver {
public void onChanged() {
// 被观察者执行操作时候,则刷新,例如刷新adapter,或者其他操作
// Adapter.notifyDataSetChanged();
}
}
// 注册观察者
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
// 注销观察者
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
public static void main(String[] args) {
ObTest obTest = new ObTest();
// 观察者类
NewDataObServer newDataObServer = new NewDataObServer();
// 注册观察者
obTest.registerDataSetObserver(newDataObServer);
// 注销观察者
// obTest.unregisterDataSetObserver(newDataObServer);
// 在Android中则把mDataSetObservable放在Application中
// 通知观察者需要更新数据
ObTest.mDataSetObservable.notifyChanged();
}
}
案例理解:
其实观察者模式就是让多个观察者对象同时监听某一个主题对象。
这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。
让主题和观察者之间松耦合。改变主题或者观察者其中一方,并不会影响另一方
例:Android广播机制(Broadcast Receiver)就是使用了观察者模式
当我需要监听网络状态是否发生改变时,只需要注册对应的监听类型,当有网络状态发生改变时,系统触发广播提醒你(如上调用:onChanged())
模式总结
- 优点
- 观察者模式解除了主题和具体观察者的耦合,让耦合的双方都依赖于抽象,而不是依赖具体。从而使得各自的变化都不会影响另一边的变化。
- 缺点
- 依赖关系并未完全解除,抽象通知者依旧依赖抽象的观察者。
- 适用场景
- 当一个对象的改变需要给变其它对象时,而且它不知道具体有多少个对象有待改变时。
- 一个抽象某型有两个方面,当其中一个方面依赖于另一个方面,这时用观察者模式可以将这两者封装在独立的对象中使它们各自独立地改变和复用。
代码下载
参考:
- 观察者模式(百度百科)
- http://www.cnblogs.com/mengdd/archive/2012/09/08/2676587.html
- http://www.cnblogs.com/mengdd/archive/2013/01/03/2843298.html
- http://www.cnblogs.com/wangjq/archive/2012/07/12/2587966.html