父博文地址:设计模式 - Design Patterns
一、是什么
定义:
观察者模式定义了对象之间的「一对多依赖」,当一的对象改变时,它所有的依赖者都能够收到通知。
行为:
一对多依赖中,「一」的一方保存所有「多」的一方的实例。
二、实例
1. 类图的实现
Subject
和ConcreteSubject
public interface Subject { void registerObserver(Observer observer); void removeObserver(Observer observer); void notifyObservers(); } public class ConcreteSubject implements Subject { private List<Observer> list = new ArrayList<>(); private Object data; @Override public void registerObserver(Observer observer) { if (!list.contains(observer)) { list.add(observer); } } @Override public void removeObserver(Observer observer) { list.remove(observer); } @Override public void notifyObservers() { for (Observer observer : list) { observer.update(data); } } public void setData(Object data) { this.data = data; notifyObservers(); } }
Observer
和ConcreteObserver
public interface Observer { void update(Object object); } public class ConcreteObserver implements Observer { @Override public void update(Object data) { System.out.println("收到数据"); // 收到数据,do something... } }
使用场景
public class MainTest { public static void main(String[] args) { // 主题 final ConcreteSubject concreteSubject = new ConcreteSubject(); // 观察者 final Observer observer1 = new ConcreteObserver(); final Observer observer2 = new ConcreteObserver(); // 注册 concreteSubject.registerObserver(observer1); concreteSubject.registerObserver(observer2); // 主题状态改变 concreteSubject.setData("模拟数据1"); // 移除一个观察者后,再次改变主题状态 concreteSubject.removeObserver(observer1); concreteSubject.setData("模拟数据2"); } }
2. Java API内置的观察者支持
主题
java.util.Observable
,和我们的一个实现类public interface Observer { void update(Observable o, Object arg); } /** * 不需要我们写“注册”、“删除”、“通知”方法的实现了。 */ public class OneSubject extends Observable { private Integer data; public void setData(Integer data) { this.data = data; // 1. 需要更改一下标志位,说明主题状态改变了 setChanged(); // 2. 超类的“通知”方法:使用这个方法表明我们要让对方从主题“拉-pull”数据 notifyObservers(); // 超类的另一个重载:使用它表明我们要“推-push”数据到观察者 // notifyObservers(data); } /** * 使用“pull”模式时,提供若干方法供调用者获取数据 */ public Integer getData() { return data; } }
观察者
java.util.Observer
,和我们的一个具体观察者public class ConcreteObserver implements Observer { @Override public void update(Observable o, Object arg) { if (o instanceof OneSubject) { final Integer data = ((OneSubject) o).getData(); System.out.println("收到数据:" + data); // 收到数据,do something... } } }
使用场景
public class MainTest { public static void main(String[] args) { // 主题 final OneSubject oneSubject = new OneSubject(); // 观察者 final ConcreteObserver concreteObserver1 = new ConcreteObserver(); final ConcreteObserver concreteObserver2 = new ConcreteObserver(); // 注册 oneSubject.addObserver(concreteObserver1); oneSubject.addObserver(concreteObserver2); // 主题状态改变 oneSubject.setData(1); } }
Java内置主题
java.util.Observable
不方便的地方主题
java.util.Observable
是实现类而不是接口,这意味着:- 具体类不能再有超类了,毕竟Java 只能单继承。
- 你无法将主题用于“组合”了,因为它的
setChanged()
是protected
的。想要使用它就必须使用“继承”。