观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知,并被自动更新。
将一个系统分割成一系列相互协作的类有一种常见的副作用,需要维护相关对象间的一致性,我们不希望为了维护一致性而使各种类紧密耦合,这样会降低它们的可重用性。观察者模式可以描述一个对象改变时,与之相关的对象状态也可以被动更新。在观察者模式中,一个Observer可以订阅任意数量的Subject,一旦Subject的状态发生改变的时候,所有的观察者都会得到通知。
观察者适用于,一个抽象模型有两个方面,其中一个方面依赖于另一个方面,或者当一个对象改变时需要同时改变其他对象,但是这些对象是运行时加入的。
public interface Observer {
public void update(Subject subject);
}
public interface Subject {
public void attach(Observer observer);
public void detach(Observer observer);
public void observerNotify();
}
public class ConcreteObserver implements Observer {
private Subject subject = null;
public ConcreteObserver(Subject subject) {
this.subject = subject;
this.subject.attach(this);
}
@Override
public void update(Subject subject) {
if (this.subject == subject) {
System.out.println("Update myself(" + this + ") and do other things!");
}
}
}
public class ConcreteSubject implements Subject {
private Set<Observer> observers = null;
public ConcreteSubject() {
observers = new HashSet<>();
}
public void attach(Observer observer) {
observers.add(observer);
}
public void detach(Observer observer) {
observers.remove(observer);
}
public void observerNotify() {
for (Observer o : observers) {
o.update(this);
}
}
}
public class Client {
@Test
public void test() {
// create a subject
Subject subject = new ConcreteSubject();
// create two observers that subscribe the subject
@SuppressWarnings("unused")
Observer observer1 = new ConcreteObserver(subject);
@SuppressWarnings("unused")
Observer observer2 = new ConcreteObserver(subject);
// subject state changed and notify all these observers
subject.observerNotify();
}
}
Subject可以被订阅,同时Subject中也会存储所有订阅了自己的Observer的集合,当Observer订阅了Subject后,只要Subject的状态改变了,就可以调用notify方法来告知所有订阅了它的Observer,这样所有Observer都会得到相应通知。
此外,在Java中是默认支持观察者模式的,它是通过Observable类和Observer接口实现了观察者模式。Observer对象是观察者,Observable对象是被观察者。当观察者事件发生时需要标记Observable的状态setChanged();把自己标记为改变的状态,然后通知所有的观察者自己的状态已经改变。
public class SubjectJava extends Observable{
private String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
setChanged();//Marks this Observable object as having been changed
notifyObservers();//notify all Observers
}
}
public class ObserverJava implements java.util.Observer{
@Override
public void update(Observable o, Object arg) {
SubjectJava suject = (SubjectJava) o;
System.out.println(suject.getState());
}
}
public class Client {
@Test
public void testJava() {
SubjectJava subject = new SubjectJava();
ObserverJava observer1 = new ObserverJava();
subject.addObserver(observer1);
subject.setState("A");
subject.setState("B");
subject.setState("C");
}
}
Java中的观察者模式比手工实现要方便很多,而且从源码上看很多Observable的方法都是同步的,故Observable可以在多线程下使用。