定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
抽象目标角色:定义目标对象,或者说被观察对象。
具体目标角色:实际的被观察对象,当这个对象发生变化时,它会通知观察它的对象。
抽象观察者角色:观察者的接口,定义了回调接口。
具体观察者角色:实际的观察者对象。当它观察的对象(被观察对象)发生变化时,被观察对象会对它进行回调。
观察者的思想就是将观察者对象的引用注册到目标对象中,目标对象存有观察者对象的引用,当目标对象发生变化的时候,目标对象就可以通过这个观察者对象的引用来回调观察者对象的某个回调函数来通知观察者,所以观察者对象可以在这个函数中进行回调的处理。
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
void notifyObservers();
}
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Vector;
public class ConcreteSubject implements Subject {
private Vector observersVector = new Vector();
public void attach(Observer observer) {
observersVector.addElement(observer);
}
public void detach(Observer observer) {
observersVector.removeElement(observer);
}
public void notifyObservers() {
Iterator observer = (Iterator) observersVector.iterator();
while(observer.hasNext()) {
Observer obs = (Observer) observer.next();
obs.update();
}
}
}
public interface Observer {
void update();
}
public class ConcreteObserver implements Observer {
public void update() {
System.out.println("The subject has changed!notify");
}
}
public class Client {
private static ConcreteSubject subject;
private static Observer observer;
public static void main(String args[]) {
subject = new ConcreteSubject();
observer = new ConcreteObserver();
subject.attach(observer);
subject.notifyObservers();
}
}
Android中的观察者模式
Android里面最典型的观察者就是我们使用的各种控件监听者。例如下面对某个按钮的监听:
Button clickButton = (Button)findViewById(R.id.button1);
//注册观察者
clickButton.setOnClickListener(new OnClickListener()
{
//观察者实现
@Override
public void onClick(View arg0)
{
Log.d("Mythou_Log", "Click the button ");
}
});
例如上面的代码,注册了一个按钮的监听方法。这里实际上是应用了一对一的观察者模式,setOnClickListener()方法就是注册一个观察者,Button对象就是我们要观察的目标对象。而new出来的OnClickListener(),就是我们实际的观察者。
每当我们的目标按钮对象被点击,状态发生变化的时候,就会通过回调注册的OnClickListener观察者的onClick方法会来通知观察者,Button状态发生变化。这里的onClick相当于前面例子里面的update方法。下面是Android源码里面对OnClickListener的定义,跟我们前面定义一个观察者接口类似。
public interface OnClickListener {
/**
* Called when a view has been clicked.
*
* @param v The view that was clicked.
*/
void onClick(View v);
}
还有一个例子比较经典,就是我们的BroadcastReceiver响应,也是基于观察者模式来实现,观察者模式支持广播通信。
A)优点
实现观察者和目标对象之间的抽象耦合。
观察者模式支持广播通信。被观察者会所有的登记过的观察者发出通知。
B)缺点
可能会引起多余的数据通知。
可能会导致通知数据循环,导致死锁产生。