观察者模式
认识
观察者模式是对象的行为模式,定义了一种一对多的依赖关系,多个观察者对象同时监听一个主题对象,当主题对象状态发生改变时,会通知所有观察者对象更新。是一种发布-订阅模式。
思考
在观察者模式中,观察者和目标是单向依赖的,只有观察者依赖目标,观察者只能被动的去等到目标的通知,等待目标传值给它。
- 推模型是假定目标知道观察者需要的数据;而拉模型是目标不知道观察者具体需要什么数据,没有办法的情况下,干脆把自身传递给观察者,让观察者自己去按需要取值。
- 推模型可能会使得观察者对象难以复用,因为观察者的update()方法是按需要定义的参数,可能无法兼顾没有考虑到的使用情况。这就意味着出现新情况的时候,就可能提供新的update()方法,或者是干脆重新实现观察者;而拉模型就不会造成这样的情况,因为拉模型下,update()方法的参数是目标对象本身,观察者可以获取目标对象上的任何非私有属性。
实质:触发联动
使用场景
- 当一个对象的改变需要通知其他对象时选用观察者模式
- 当一个抽象模型有两个方面,一个方面的操作依赖另一个方面的状态变化时选用观察者模式
优缺点
优点
- 实现了观察者和目标之间的解耦合
- 支持广播通知
缺点
UML图
定义一个目标抽象类,在抽象类中维护一个观察者的list,通过准备阶段创建观察者add到list中,提供添加和删除观察者的方法,提供通知观察者的方法。
定义一个目标具体实现类,在该实现类中如果发生变化调用notifyObserves通知所有观察者
定义一个观察者接口和一系列观察者实现类对象,提供方法供目标回调
● 目标(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象,提供目标更新时通知观察者的方法。
● 目标实现(ConcreteSubject)角色:具体目标实现,用来维护目标状态,当目标状态发生改变时通知已注册的所有观察者。
● 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,定义目标对象通知观察者时的回调方法。
● 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者接收通知进行后续处理。
- 准备阶段
- 运行阶段
代码实现
推模型
目标回调观察者时传入具体的值
//目标抽象类
public abstract class Subject {
// 注册的观察者列表
private List<Observer> observerList = new ArrayList<Observer>();
// 注册观察者
public void attach(Observer observer) {
observerList.add(observer);
}
// 移除观察者
public void detach(Observer observer) {
observerList.remove(observer);
}
// 定义通知方法
protected void nodifyObservers(String newState) {
for(Observer observer:observerList){
observer.update(newState);
}
}
}
//目标具体实现类
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
//目标更新时通知所有观察者
public void change(String newState) {
state = newState;
System.out.println("主题状态为:" + state);
// 状态发生改变,通知各个观察者
this.nodifyObservers(state);
}
}
//观察者接口
public interface Observer {
//提供方法供目标回调通知并传入值
public void update(String state);
}
//观察者具体实现类
public class ConcreteObserver implements Observer {
//观察者的状态
private String observerState;
//通过目标回调获取目标传递给回来的值
public void update(String state) {
/**
* 更新观察者的状态,使其与目标的状态保持一致
*/
observerState = state;
System.out.println("状态为:"+observerState);
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
//创建目标
ConcreteSubject subject = new ConcreteSubject();
//创建观察者
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
//注册观察者
subject.attach(observer1);
subject.attach(observer2);
//更新目标并通知所有观察者
subject.change("new");
subject.detach(observer2);
subject.change("again");
}
}
拉模型
目标回调观察者时将目标对象传递给观察者
//目标抽象类
public abstract class Subject {
// 注册的观察者列表
private List<Observer> observerList = new ArrayList<Observer>();
// 注册观察者
public void attach(Observer observer) {
observerList.add(observer);
}
// 移除观察者
public void detach(Observer observer) {
observerList.remove(observer);
}
// 定义通知方法,直接将目标对象回调传递给观察者
protected void nodifyObservers() {
for(Observer observer:observerList){
observer.update(this);
}
}
}
//目标具体实现类
public class ConcreteSubject extends Subject {
private String state;
public String getState() {
return state;
}
//目标更新时通知所有观察者
public void change(String newState) {
state = newState;
System.out.println("主题状态为:" + state);
//将目标对象通过回调传递给每个观察者
this.nodifyObservers();
}
}
//观察者接口
public interface Observer {
//提供方法供目标回调通知并传入值
public void update(Subject subject);
}
//观察者具体实现类
public class ConcreteObserver implements Observer {
//观察者的状态
private String observerState;
//通过目标回调获取目标对象
@Override
public void update(Subject subject) {
//通过目标对象的引用获取目标对象中的值
observerState = ((ConcreteSubject)subject).getState();
System.out.println("状态为:"+observerState);
}
}
//客户端调用
public class Client {
public static void main(String[] args) {
//创建目标
ConcreteSubject subject = new ConcreteSubject();
//创建观察者
Observer observer1 = new ConcreteObserver();
Observer observer2 = new ConcreteObserver();
//注册观察者
subject.attach(observer1);
subject.attach(observer2);
//更新目标并通知所有观察者
subject.change("new");
subject.detach(observer2);
subject.change("again");
}
}
jdk提供的接口
//目标对象继承Observable接口
public class Watched extends Observable接口{
private String data = "";
public String getData() {
return data;
}
public void setData(String data) {
if(!this.data.equals(data)){
this.data = data;
setChanged();
}
notifyObservers();
}
}
//观察者实现Observer接口
public class Watcher implements Observer{
public Watcher(Observable o){
o.addObserver(this);
}
@Override
public void update(Observable o, Object arg) {
System.out.println("状态发生改变:" + ((Watched)o).getData());
}
}
public class Client {
public static void main(String[] args) {
//创建被观察者对象
Watched watched = new Watched();
//创建观察者对象,并将被观察者对象登记
Observer watcher = new Watcher(watched);
//给被观察者状态赋值
watched.setData("start");
watched.setData("run");
watched.setData("stop");
}
}