观察者模式
GOF概括:定义对象间的一种一对多的依赖关系,当一个对象的状态发生变化时,所有依赖它的对象都得到通知并被自动更新。
概述
这个可能是最早接触,但是,越学越复杂的设计模式了。
主要是因为 “观察者模式” 可以引申出非常多的知识点:“发布-订阅者模式”、“消息队列”……
观察者模式是非常重要的一个设计模式,你几乎能在任何项目见到观察者模式的应用,并且会伴随着程序员走完整个职业生涯。
- 简单地说,就是一个对象,做了某件事,另一个对象要接着做点啥;
- 往大了说,卫星拍了一张照,新闻上你可能看到,天气系统也能看到(一个系统更新消息,无数下游的服务需要侦听消息变化);
- 往小了说,就比如你 update 一条数据,日志系统要记录你的操作(一个模块的更新,另一个模块随之变化)。
推送场景
这种代码结构非常常见,基本是要求背诵的。
一下子就能想到的,就是各种点击事件,例如:xxxClickListener(Event e)。
import java.util.ArrayList;
import java.util.List;
interface Observer{
// 侦听函数
void onAction(String action);
}
class Subject{
// 观察者集合
List<Observer> list = new ArrayList<>();
// 一个业务流
public void run(){
// do sth.
// then
notifyObserver("ok");
}
// 做完一件事情之后,触发所有观察者的侦听函数
public void notifyObserver(String action){
for(Observer observer: list){
observer.onAction(action);
}
}
}
拉取场景
拉取模式与推送模式的区别是:收到消息之后,可以根据需求,拉取不同的数据。
说实话,对于 “拉取模式” 这个词,我是有些怀疑的,像是老师为了为难学生,自己创造出来的名词。
- 首先,代码本身就有点不伦不类的感觉,Observer 必须 import Subject,观察者与主题之间产生了耦合,正常应该只与消息产生耦合;
- 然后,去找 “观察者模式” 的文章,经常看不到 “拉取模式” 的相关内容;
- 最后,这并没有改变 “推送模式” 的本质,就比如下面代码,把 getMsg1() 放到另一个类,代码还是标准的推送模式。
不管具体怎样,不排除面试时,可能有人会这么问你,很多人都是这么学的,所以还是要掌握一下。
import java.util.ArrayList;
import java.util.List;
class Observer{
// 一个侦听函数
public void onAction(Subject action){
System.out.println(action.getMsg1());
}
}
class Subject{
List<Observer> list = new ArrayList<>();
// 一个业务流
public void run(){
// do sth.
notifyObserver();
}
// 获取消息 a
public String getMsg1(){
return "message1";
}
// 获取消息 b
public String getMsg2(){
return "message2";
}
// 通知所有的观察者
public void notifyObserver(){
for(Observer observer: list){
observer.onAction(this);
}
}
}
JDK标准实现
JDK 的 java.util 包提供了标准接口,可能整个职业生涯都用不上,
当然,多少要了解一些,因为面试可能会被提问。
实在不想了解,可以这么和面试官解释:因为 java 是单继承,Observable 的设计注定不会太实用;
业务上,需求往往十分复杂,使用 Observable 这样一个不常用、又很复杂的类,可能会增加维护负担。
一些文章认为,JDK 的实现是拉取模式,因为 update() 第一个参数是 Observable,
但是实际上,一个观察者,可以侦听很多消息,Observable 本身就是必要的,需要用它确定消息来源。
import java.util.Observable;
import java.util.Observer;
class Obs implements Observer {
@Override
public void update(Observable o, Object arg) {
System.out.println(o);
System.out.println(arg);
}
}
class Subject extends Observable{
public void run(){
// do sth.
super.setChanged();
super.notifyObservers("msg");
}
}
public class Test2 {
public static void main(String[] args) {
Obs obs = new Obs();
Subject subject = new Subject();
subject.addObserver(obs);
subject.run();
}
}
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!
浙公网安备 33010602011771号