某一个事件的发生需要通知多个组件的时候。 注意这里是“多个”,如果是单个组件完全可以使用回调的方式。
JDK已经帮我们定义好了观察者模式的接口(java.util.Observale;java.util.Observer),我们如果项目中需要使用观察者模式,只需简单继承一下就可以了,JDK保证了线程安全。
Observable对象维护了一个ArrayList<监听者>,通过回调通知订阅者。 主要方法:notifyObservers,addObserver
Observer 对象需要实现的方法 update(),供Observable回调使用。
java.util.Observale源码:
for(Observer observer ; ObserverList){
public void notifyObservers(Object arg) {
/*
* a temporary array buffer, used as a snapshot of the state of
* current Observers.
*/
Object[] arrLocal;
synchronized (this) {
if (!changed)
return;
arrLocal = obs.toArray();
clearChanged();
}
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
下面的一个例子是,出版社出版了一个杂志,要读者主动订阅。
发布者
public class Publisher extends Observable{
private String magazineName;
public String getMagazineName() {
return magazineName;
}
public void setMagazineName(String magazineName) {
this.magazineName = magazineName;
}
public void publish (String magazineName){
this.magazineName = magazineName;
this.setChanged();
this.notifyObservers(this);
}
}
订阅者
public class Reader implements Observer {
@Override
public void update(Observable arg0, Object arg1) {
if(arg0 instanceof Publisher){
Publisher publisher = (Publisher)arg0;
System.out.println("有新杂志。我要订阅"+publisher.getMagazineName());
}
}
}
public class TestCase {
public static void main(String[] args) {
// TODO Auto-generated method stub
Publisher publisher = new Publisher();
Reader zhangsan = new Reader();
publisher.addObserver(zhangsan);
Reader lisi = new Reader();
publisher.addObserver(lisi);
publisher.publish("程序员第0321期");
//结果
//有新杂志。我要订阅 程序员第0321期
}
}
Android ContentService 的观察者模式
public interface ContentObserver {
public void onChange(boolean stateNow);
}
定义观察者
public class Activity implements ContentObserver{
@Override
public void onChange(boolean stateNow) {
}
}
import java.util.ArrayList;
public class Context {
private ArrayList<ContentObserver> observerList = new ArrayList<ContentObserver>();
public final void registerContentObserver(ContentObserver observer){
observerList.add(observer);
}
public final void UnregisterContentObserver(ContentObserver observer){
observerList.remove(observer);
}
public void notifyChange(boolean state) {
for(ContentObserver observer : observerList){
observer.onChange(state);
}
}
}
public static void main(String[] args) {
Activity a1 = new Activity1();
Activity a2 = new Activity2();
//context是被观察者
Context context = new Context();
context.registerContentObserver(a1);
context.registerContentObserver(a2);
context.notifyChange(false);
}
上述代码的问题是没有注意线程安全问题,Context中的registerContentObserver、UnregisterContentObserver应该加上Synchronized进行线程同步控制。