观察者模式定义了对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。例如,当上课时间到时,铃声便会响起通知老师和同学们准备去上课了。
类图:
代码实现:
观察者接口:
package com.demo.observer.observer;
public interface Observer {
public void update();
}
老师类(具体的观察者):
package com.demo.observer.observer;
public class Teacher implements Observer {
public Teacher() { }
@Override
public void update() {
System.out.println("铃声响了,老师准备去上课。");
}
}
学生类(具体的观察者):
package com.demo.observer.observer;
public class Student implements Observer {
public Student() { }
@Override
public void update() {
System.out.println("铃声响了,学生准备去听课。");
}
}
主题接口:
package com.demo.observer.subject;
public interface Subject {
public void addObserver(Observer observer); // 注册观察者
public void removeObserver(Observer observer); // 移除观察者
public void notifyObservers(); // 通知所有观察者
}
铃钟类(具体的主题):
package com.demo.observer.subject;
import java.util.ArrayList;
import java.util.List;
public class Bell implements Subject {
private List<Observer> observers; // 维护所有注册的观察者
public Bell() {
observers = new ArrayList<Observer>();
}
/*
* 铃声响起
*/
public void ring() {
notifyObservers();
}
@Override
public void addObserver(Observer observer) {
observers.add(observer);
}
@Override
public void removeObserver(Observer observer) {
observers.remove(observer);
}
@Override
public void notifyObservers() {
for (Observer observer : observers) {
observer.update();
}
}
}
测试代码:
package com.demo.observer;
import com.demo.observer.observer.Student;
import com.demo.observer.observer.Teacher;
import com.demo.observer.subject.Bell;
public class MainApp {
public static void main(String[] args) {
Bell bell = new Bell();
bell.addObserver(new Teacher());
bell.addObserver(new Student());
bell.ring();
}
}
结果输出:
铃声响了,老师准备去上课。
铃声响了,学生准备去听课。
Java内置的观察者模式,JDK已经定义好了抽象主题和抽象观察者,即java.util.Observable和java.util.Observer。
类图:
代码实现:
老师类:
package com.demo.observer.observer;
import java.util.Observable;
import java.util.Observer;
public class Teacher implements Observer {
public Teacher() { }
@Override
public void update(Observable o, Object arg) {
System.out.println("铃声响了,老师准备去上课。");
}
}
学生类:
package com.demo.observer.observer;
import java.util.Observable;
import java.util.Observer;
public class Student implements Observer {
public Student() { }
@Override
public void update(Observable o, Object arg) {
System.out.println("铃声响了,学生准备去听课。");
}
}
铃钟类:
package com.demo.observer.subject;
import java.util.Observable;
public class Bell extends Observable {
public Bell() {
}
/*
* 铃声响起
*/
public void ring() {
setChanged(); // 调用该方法表示主题的状态发生了改变
notifyObservers();
}
}
测试代码:
package com.demo.observer;
import com.demo.observer.observer.Student;
import com.demo.observer.observer.Teacher;
import com.demo.observer.subject.Bell;
public class MainApp {
public static void main(String[] args) {
Bell bell = new Bell();
bell.addObserver(new Teacher());
bell.addObserver(new Student());
bell.ring();
}
}
结果输出:
铃声响了,学生准备去听课。
铃声响了,老师准备去上课。
注意到,这时候Observable是一个类而不是一个接口,这意味着当我们想同时具有Observable类和另一个超累的行为时,就会陷入两难,因为Java不支持多继承。再注意到,setChanged()方法是protected的,这意味着除非我们继承Observable类,否则我们无法创建Observable实例并组合到自己的对象中来。所以在必要的时候,我们需要实现自己的观察者模式。