观察者模式是一个使用率非常高的的模式,它是一套订阅——发布系统,这个模式最重要的作用就是将订阅者和被订阅者解耦。
一、定义
定义对象间一种对多种的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知。
UML:
Subject:抽象主题类,也就是被观察者(Observable),把所有观察者对象保存在一个集合里,每个被观察者都可以有任意数量的观察者,并且可以增加和删除观察着对象。
ConcreteSubject:具体主题,也就是具体被观察者,器内部状态改变时,可以给所有注册过的观察者发送通知。
Observer:抽象观察者,它定义一个更新接口,使得在主题更改的时候通知自己。
ConcreteObserver:具体观察者
二、使用场景
1、事件会多级触发的场景
2、需要解耦并且有事件传递(或作出相应改变)的若干个类的场景
3、有时可以用到跨系统的消息交换场景,如消息队列、事件总线的处理机制。
三、示例
Observer和Observable是JDK中的内置类,可见观察者模式是多么的常用和重要,为了更深一层的了解观察者模式,这里我们自己写一个简单的观察者模式示例,试想这么一种场景:小明和大明同喜喜爱一本叫《白雪公主》的书,并且同事订阅了这本书,当这本书发售新期刊的时候,要通知到小明的大明,首先我们需要一个被观察者(Observable)的基类Book:
public abstract class Book {
/**
* 注册观察者
*/
public abstract void addObservable(Observer observer);
/**
* 注销观察者
*/
public abstract void removeObservable(Observer observer);
/**
* 通知变化
*/
public abstract void update();
}
接下来是《白雪公主》:
public class SnowWhite extends Book {
/**
* 持有一个观察者的集合
*/
private List<Observer> list = new ArrayList<>();
/**
* 期刊数
*/
private int periodical;
public void setPeriodical(int periodical) {
this.periodical = periodical;
//当期刊变化时,通知所有的观察者
update();
}
@Override
public void addObservable(Observer observer) {
list.add(observer);
}
@Override
public void removeObservable(Observer observer) {
list.remove(observer);
}
@Override
public void update() {
for (Observer o : list) {
o.onUpdate(this, periodical);
}
}
}
接下来写一个观察者的基类:
public interface Observer {
void onUpdate(Book book, Object change);
}
小明和大明作为观察者,需要实现观察者基类:
public class XiaoMing implements Observer {
@Override
public void onUpdate(Book book, Object change) {
System.out.println("小明:我喜欢的书更新到第" + change + "期啦!");
}
}
public class DaMing implements Observer {
@Override
public void onUpdate(Book book, Object change) {
System.out.println("大明:我喜欢的书更新到第" + change + "期啦!");
}
}
好了,我们先让小明和大明订阅这本书,然后去更新这本书的期刊:
public static void main(String[] args) {
XiaoMing xiaoMing = new XiaoMing();
DaMing daMing = new DaMing();
SnowWhite snowWhite = new SnowWhite();
snowWhite.addObservable(xiaoMing);
snowWhite.addObservable(daMing);
snowWhite.setPeriodical(2);
snowWhite.setPeriodical(3);
}
log如下:
小明:我喜欢的书更新到第2期啦!
大明:我喜欢的书更新到第2期啦!
小明:我喜欢的书更新到第3期啦!
大明:我喜欢的书更新到第3期啦!
可以看到所有订阅书籍的然都收到了通知,一对多的订阅——发布系统就完成了。