观察者模式
概念
观察者模式(Observer)属于行为型模式,其又被称为订阅–发布模式(Publish/Subscribe),用于当一个对象的状态发生改变时,所有依赖它的对象都能够得到通知并被自动更新。
类图
模式角色
Subject:待观察对象的接口,Observer将自己注册进Subject或者取消注册,每个Subject可以对应多个Observer
ConcreteSubject:具体的待观察的对象,除了注册和注销之外,还需要在某个状态改变时调用notifyObservers方法。当然也得实现获取和设置状态的方法
Observer:所有的观察者都必须实现该接口,这个接口有个update方法,当待观察者某个状态改变时,这个方法会被调用
ConcreteObserver:具体的观察者,实现了Observer接口
实例
public abstract class Subject {
private List<Observer> mObservers = new ArrayList<Observer>();
public void registerObserver(Observer observer) {
mObservers.add(observer);
}
public void unregisterObserver(Observer observer) {
mObservers.remove(observer);
}
public void notifyObservers() {
for (Observer observer : mObservers) {
observer.update();
}
}
public abstract void setValue(int value);
public abstract int getValue();
}
public class ConcreteSubject extends Subject {
private int value;
public void setValue(int value) {
this.value = value;
notifyObservers();//通知注册的观察者,状态已经更新
}
public int getValue() {
return value;
}
}
Observer对象
public interface Observer {
public void update();
}
ConcreteObserver对象
public class ConcreteObserver implements Observer {
public void update() {
System.out.println("State changed");
}
}
Client对象
public class Client {
public static void main (String[] args) {
Subject subject = new ConcreteSubject();
Observer observer = new ConcreteObserver();
subject.registerObserver(observer);
subject.setValue(1);
}
}
优缺点
优点:
- Subject和Observer之间是松偶合的,分别可以各自独立改变,提高了可维护性。
- 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合。
缺点:
- 如果Subject被大量Observer订阅的话,在分发通知时,会有效率问题
应用场景:
1、 对一个对象状态的更新,需要其他对象同步更新,而且其他对象的数量动态可变。
2、 对象仅需要将自己的更新通知给其他对象而不需要知道其他对象的细节。
Java语言自带的观察者模式
Java util包里提供了Observable和Observer类,用于简化观察者模式的实现。
Subject对象
public static class MySubject extends Observable {
public void set(int value) {
setChanged();
notifyObservers(value);
}
}
Observer对象
public static class MyObserver implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println("update Observer " + o + " arg " + arg);
}
}
这里Subject需要继承Observable类,MyObserver需要实现Observer接口,并实现update方法,Subject里在状态变化后,需要先调用setChanged方法,标志状态变化,然后调用notifyObservers方法通知所有的观察者,并会顺序调用这些观察者的update方法。
注意notifyObservers会检测状态是否发生变化,即setChanged方法是否设置过,若没有则不会调用观察者的update方法。
Android中的观察者模式
Android中的广播,各种view的点击事件的监听等均是观察者模式的体现。