Design Pattern 之 观察者模式
Posted 月盡天明
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Design Pattern 之 观察者模式相关的知识,希望对你有一定的参考价值。
转载请注明出处:http://blog.csdn.net/crazy1235/article/details/51815880
观察者模式介绍
观察者模式 又称为 发布-订阅模式 。定义了一种一对多的依赖关系,当被观察者对象状态发生改变时,通知所有依赖于它(订阅它)的观察者对象。
RSS订阅 和 邮件订阅 大家应该都知道,你订阅后,将会及时获得所订阅的相关最新内容。所有订阅该内容的“订阅者”,当该内容有更新时,就可以收到通知。这就是一种观察者模式的应用场景。
UML图
java中,内置了Observer和Observable,分别表示抽象的观察者对象和抽象主题角色(可被观察,被观察者)。
Observer是一个借口,定义了一个update方法。
public interface Observer {
void update(Observable o, Object arg);
}
观察者模式应用
先来看看JDK中Observer和Observable的源码。
Observer
public interface Observer {
/**
* 更新操作
*/
void update(Observable o, Object arg);
}
该类是一个 接口 ,只有一个更新的函数。
Observable
package java.util;
/**
* 表示一个可被观察的对象
* 一个被观察者可以有多个观察者对象
* 调用 notifyObservers 方法可以通知所有的观察者调用他们的 update 方法
* 当一个被观察者被初始创建的时候,它的观察者set集合是空的
*/
public class Observable {
private boolean changed = false;
private Vector<Observer> obs; // 通过向量保存观察者对象
/** Construct an Observable with zero Observers. */
public Observable() {
obs = new Vector<>();
}
/**
* 添加一个观察者对象
*
* @param o an observer to be added.
* @throws NullPointerException if the parameter o is null.
*/
public synchronized void addObserver(Observer o) {
if (o == null)
throw new NullPointerException();
if (!obs.contains(o)) {
obs.addElement(o);
}
}
/**
* 删除一个观察者对象
*
* @param o the observer to be deleted.
*/
public synchronized void deleteObserver(Observer o) {
obs.removeElement(o);
}
/**
* 当对象发生变化是,首先调用hasChanged表明发生了改变,然后通知所有的观察者对象,调用它们各自的update方法,最后调用clearChanged方法表明当前对象已经没有改变了。
* 每个观察者对象都有它的update方法,该方法有两个参数
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
* arg参数最终会赋值给update函数的第二个参数
*
* @param arg any object.
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#hasChanged()
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
//由此可以看书,如果没有changed == false,直接return,后序代码不执行。
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
//倒序遍历观察者对象数组,调用update方法。由此看出,后添加进来的观察者对象会被先调用update方法。
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
/**
* 清楚所有的观察者对象
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
* 设置改变标志,只有调用了该方法,观察者对象才能被通知。
*/
protected synchronized void setChanged() {
changed = true;
}
/**
* 重置改变标志
*
* @see java.util.Observable#notifyObservers()
* @see java.util.Observable#notifyObservers(java.lang.Object)
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
* 判断是否有改变
*
* @see java.util.Observable#clearChanged()
* @see java.util.Observable#setChanged()
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
* 返回观察者对象的数量
*/
public synchronized int countObservers() {
return obs.size();
}
}
基本应用
/**
* 被观察者类 继承Observable类,表示这个类可以被观察。
*
* @author Admin
*
*/
public class SimpleObservable extends Observable {
private int data = 0;
public int getData() {
return data;
}
public void setData(int data) {
if (this.data != data) {
this.data = data;
// 标志状态改变,一定要调用函数notify方法才有效
setChanged();
// 通知所有观察者
notifyObservers("abc");
}
}
}
/**
* 观察者1号
*
* @author Admin
*
*/
public class SimpleObserver implements Observer {
public SimpleObserver(SimpleObservable simpleObservable) {
simpleObservable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
System.out.println("SimpleObserver: " + ((SimpleObservable) o).getData() + " -- " + (String)arg);
}
}
/**
* 观察者2号
* @author Admin
*
*/
public class OtherObserver implements Observer{
public OtherObserver(SimpleObservable observable){
observable.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
System.out.println("OtherObserver: " + ((SimpleObservable)o).getData() + " -- " + (String)arg);
}
}
public class SimpleTest {
public static void main(String[] args) {
SimpleObservable observable = new SimpleObservable();
new OtherObserver(observable);
new SimpleObserver(observable);
observable.setData(1);
observable.setData(2);
observable.setData(2);
observable.setData(4);
}
}
测试的结果如下:
SimpleObserver: 1 -- abc
OtherObserver: 1 -- abc
SimpleObserver: 2 -- abc
OtherObserver: 2 -- abc
SimpleObserver: 4 -- abc
OtherObserver: 4 -- abc
异步观察者模式
上面介绍的都是同步观察者模式。同步观察者模式会有阻塞问题。各个观察者按照顺序执行update方法。一旦有一个observer比较耗时的话,后序的observer也得等着。
异步观察者模式就不一样,不会有这样的阻塞问题。
针对update方法做文章 。
/**
* 异步观察模式的观察者接口
*/
public interface AsyncObserver {
/**
*
* @param o
* @param arg
*/
void update(AsyncObservable o, Object arg);
}
/**
* 异步观察者模式的被观察者对象
*/
public class AsyncObservable {
private boolean changed = false;
private Vector<Wrapper> obs;
public AsyncObservable() {
obs = new Vector<>();
}
/**
*
* @param wrapper
*/
public synchronized void addObserver(AsyncObserver o) {
if (o == null)
throw new NullPointerException();
Wrapper wrapper = new Wrapper(o);
if (!obs.contains(wrapper)) {
obs.addElement(wrapper);
}
}
/**
*
*/
public synchronized void deleteObserver(AsyncObserver o) {
Iterator<Wrapper> iterator = obs.iterator();
while (iterator.hasNext()) {
Wrapper wrapper = iterator.next();
if (wrapper.getAsyncObserver() == o) {
obs.remove(wrapper);
break;
}
}
}
/**
*
*/
public void notifyObservers() {
notifyObservers(null);
}
/**
*
*/
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length - 1; i >= 0; i--)
((Wrapper) arrLocal[i]).update(this, arg);
}
/**
*
*/
public synchronized void deleteObservers() {
obs.removeAllElements();
}
/**
*
*/
protected synchronized void setChanged() {
changed = true;
}
/**
*
*/
protected synchronized void clearChanged() {
changed = false;
}
/**
*
*/
public synchronized boolean hasChanged() {
return changed;
}
/**
*
*/
public synchronized int countObservers() {
return obs.size();
}
}
/**
* 观察者的包装类
*/
public class Wrapper {
private AsyncObserver observer;
public Wrapper(AsyncObserver o) {
this.observer = o;
}
public AsyncObserver getAsyncObserver() {
return observer;
}
/**
*
* @param observable
* @param o
*/
public void update(AsyncObservable observable, Object o) {
new Handler(observable, o).start();
}
class Handler extends Thread {
AsyncObservable observable;
Object object;
public Handler(AsyncObservable observable, Object o) {
this.observable = observable;
this.object = o;
}
@Override
public void run() {
observer.update(observable, object);
}
}
}
最主要的就是这个Wrapper包装类。被观察者的notify方法内部实际上调用的是Wrapper类中的update()方法。
将每个update操作放到一个线程中去。这样多个线程“同时”工作。
这样即是某些观察者类的update做一些耗时操作,也不影响其他观察者类的update的工作、
测试结果:
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
hahahaha
ObserverB -- i think jingjing -- jingjing
hahahaha
ObserverC -- i think jingjing -- jingjing
ObserverA -- i think jingjing -- jingjing
总结
观察者模式中,被观察者与观察者通过接口进行联系。被观察者只知道一个观察者列表,列表中的每个对象都是一个抽象观察者接口。
android中观察者模式的应用场景有:
广播机制
ListView数据更改
点击事件
ContentObserver
完毕。
:-D
晚安~
以上是关于Design Pattern 之 观察者模式的主要内容,如果未能解决你的问题,请参考以下文章