其目的是定义对象之间的一对多以来,让多个观察者对象同时监听一个对象
push模式(set)
public interface Observer {
void update(float temperature);//更新天气信息
}
//管理观察者
public interface Subject {
void registerObserver(Observer o);//注册观察对象
void removeObserver(Observer o);//移除观察对象
void notifyObservers();//通知观察对象
}
//被观察者
public class WeatherData implements Subject {
private List<Observer> observers;//观察者不止一个,所以用list进行维护
private float temperature;//温度
public void setMessurements(float temperature){
this.temperature = temperature;
notifyObservers();//气温信息发生变化时,通知所有观察者
}
public WeatherData() {//初始化list
this.observers = new ArrayList<>();
}
/**
* 注册观察者
* @param o
*/
@Override
public void registerObserver(Observer o) {
observers.add(o);
}
/**
* 移除观察者
* @param o
*/
@Override
public void removeObserver(Observer o) {
int i = observers.indexOf(o);
if(i >= 0){
observers.remove(i);
}
}
/**
* 通知所有观察者
*/
@Override
public void notifyObservers() {
for (Observer observer : observers){//遍历所有观察者
observer.update(temperature);//通知观察者更新数据信息
}
}
}
//观察者
public class WeatherDisplay implements Observer {
private Subject subject;//维护观察者
private float temperature;//温度
public WeatherDisplay(Subject subject) {//注册监听对象
this.subject = subject;
subject.registerObserver(this);
}
@Override
public void update(float temperature) {//当被观察者气温发生变化会调用这个方法,也就等于更新了观察者对象的数据
this.temperature = temperature;
}
public void display(){
System.out.println("当前最新的温度为:" + temperature);
}
}
pull 模式
//记录动态信息
public class Trends {
private String nickName;//发表动态的用户昵称
private String content;//发表的动态内容
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
//(被观察者),继承 JDK 自带的被观察者对象:Observable
public class Zone extends Observable {
//发表动态
public void publishTrends(Trends trends){
System.out.println(trends.getNickName() + "发表了一个动态【" + trends.getContent() + "】" );
setChanged();//占位,只是设置一个标记说明数据改变了
notifyObservers(trends);//通知所有观察者
}
}
//(观察者),实现 JDK 自带的观察者接口:Observer
public class Friends implements Observer {
private String name;//看动态的人名
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void update(Observable o, Object arg) {//获取(空间)被观察者数据
Trends trends = new Trends();
if(null != arg && arg instanceof Trends){
trends = (Trends)arg;
}
System.out.println(this.getName() + ",您好!您收到了来自" + trends.getNickName() +
"的一条动态【" + trends.getContent() + "】" + "快去点赞吧!");
}
}
JDK 自带的观察者模式的局限性:
- JDK 自带的观察者模式虽然可以主动去 pull 自己需要的数据,但也同时存在以下两个问题:
- Observable 是一个类而不是一个接口,所以复用性就不是很好,如果某类同时想具有 Observable 类和另一个超类的行为,就会有问题,毕竟 Java 不支持多继承。
- Observable 将关键的方法保护起来了,比如 setChanged 方法,也就是我们只能继承 Observable 类才能实现想要的功能,这个违反了合成复用原则.
适用场景:
需要实时监听数据
优点:
扩展性好,要扩展观察者只需要新建观察者并注册进去就可以
缺点:
被观察者对象过多时,会使得系统复杂难以维护