Fork me on GitHub

设计模式之一 观察者模式

观察者模式

观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。 这个主题对象在状态上发生变化时,会通知所有观察者对象,让它们能够自动更新自己。

观察者模式,主要有两个类Subject,Observer,Subject表示被观察对象,Observer表示观察者,当subject发生变化时,通知所有观察者做出对应方法,比如,气象台更新气温,pc,app更新气温

代码示例
主题Subject 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//主题
public interface Subject {
void addObserver(Observer observer);//添加观察者

void removeObserver(Observer observer);//删除

void notifyObserver();//通知
}

// 具体主题,天气
public class WeatherSubject implements Subject {

private float temperature;//温度

private float humidity;//湿度

private float pressure;//气压

private List<Observer> observers; // 所有观察者

public WeatherSubject() {
observers = new ArrayList<>();
}

@Override
public void addObserver(Observer observer) {
observers.add(observer);
}

@Override
public void removeObserver(Observer observer) {
if (observers.contains(observer)) {
observers.remove(observer);
}
}

@Override
public void notifyObserver() {
observers.stream().forEach(observer -> observer.update(this));
}

// 测量天气
public void messurements(float temperature, float humidity, float pressure) {
this.temperature = temperature;
this.humidity = humidity;
this.pressure = pressure;
notifyObserver();//每次测量后通知给观察者
}
}

观察者代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//观察者
public interface Observer {

void update(Subject subject);
}

// PC天气
public class PCWeahtherObserve implements Observer {
@Override
public void update(Subject subject) {
WeatherSubject weatherSubject = (WeatherSubject) subject;
System.out.println("PC更新温度为:"+weatherSubject.getTemperature()+
"湿度为:"+weatherSubject.getHumidity()+
"大气为:"+weatherSubject.getPressure());
}
}
//APP天气
public class AppWeatherObserver implements Observer{

@Override
public void update(Subject subject) {
WeatherSubject weatherSubject = (WeatherSubject) subject;
System.out.println("app更新温度为:"+weatherSubject.getTemperature()+
"湿度为:"+weatherSubject.getHumidity()+
"大气为:"+weatherSubject.getPressure());
}
}

测试

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
WeatherSubject weatherSubject = new WeatherSubject();
PCWeahtherObserve pcWeahtherObserve = new PCWeahtherObserve();
AppWeatherObserver appWeatherObserver = new AppWeatherObserver();
weatherSubject.addObserver(pcWeahtherObserve);
weatherSubject.addObserver(appWeatherObserver);
weatherSubject.messurements(23f, 4.5f, 6.7f);
}

结果
PC更新温度为:23.0湿度为:4.5大气为:6.7
app更新温度为:23.0湿度为:4.5大气为:6.7

当以后再增加天气显示类型时,不用动之前代码,新添加Observer,并将添加到主题观察列表即可

事件模式

事件为也为观察者模式,事件通常有三个要素,事件,事件源,事件监听器,事件流程通常为【事件源注册监听器】–> 【事件发生,事件源向监听器发送事件】 –> 【事件监听器响应事件】

需求:订单出库后,订单生成报表,并统计员工绩效

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//事件
public interface Event {
}


/*事件监听器*/
public interface EventListener {
void listener(Event event);
}

//以下为具体实现
//具体事件
public class OrderEvent implements Event {

private String orderCode;

/*....setter,getter*/
}

/*事件源*/
public class OrderEventSource {

private List<EventListener> listeners;

public void addListener(EventListener eventListener) {//注册监听器
if (listeners == null) {
listeners = new ArrayList<>();
}
listeners.add(eventListener);
}

@Override
public void onEvent(Event event) {//发布事件
listeners.forEach(listeners->listeners.listener(event));
}
}

// 事件监听器,插入报表
public class OrderReportListener implements EventListener {
@Override
public void listener(Event event) {
if (event instanceof OrderEvent) {
OrderEvent orderEvent = (OrderEvent) event;
System.out.println("订单"+orderEvent.getOrderCode()+"已经发货,插入报表");
}
}
}


// 事件监听器,插入绩效
public class OrderListener implements EventListener {
@Override
public void listener(Event event) {
if (event instanceof OrderEvent) {
OrderEvent orderEvent = (OrderEvent) event;
System.out.println("订单编码" + orderEvent.getOrderCode() + "已发货,插入绩效表中");
}
}
}

//测试
public static void main(String[] args) {
OrderEvent orderEvent = new OrderEvent();
orderEvent.setOrderCode("yuanwj");

OrderEventSource orderEventSource = new OrderEventSource();
OrderListener orderListener = new OrderListener();
OrderReportListener orderReportListener = new OrderReportListener();
orderEventSource.addListener(orderListener);
orderEventSource.addListener(orderReportListener);


orderEventSource.onEvent(orderEvent);
}
//结果
//订单编码yuanwj已发货,插入绩效表中
//订单yuanwj已经发货,插入报表

SpringBoot事件设计模式应用

springboot自己配置listener的执行过程,当一个事件源产生事件时,它通过事件发布器ApplicationEventPublisher发布事件,然后事件广播器ApplicationEventMulticaster会去事件注册表ApplicationContext中找到事件监听器ApplicationListnener,并且逐个执行监听器的onApplicationEvent方法,从而完成事件监听器的逻辑。

springboot中事件执行过程为 springboot通过spring-boot.war包下spring.factories加载所有listener,并维护到事件广播器ApplicationEventMulticaster,启动中事件发生,调用ApplicationEventMulticaster发布,并逐个执行监听器onSPplicationEvent方法,后续与自建事件类型

事件伴随springboot启动的整个周期,下面从springboot 前置加载Environment 分析事件及ApplicationEnvironmentPreparedEvent在springboot中的应用

代码示例
springboot启动代码 其他忽略,只分析this.prepareEnvironment(listeners, applicationArguments);
这一行代码,这行代码为enviroment预处理,其中包括选取哪个配置文件及配置文件加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;
this.configureHeadlessProperty();
SpringApplicationRunListeners listeners = this.getRunListeners(args);//创建ApplicationEventMulticaster,并将spring.factories配置listener维护到ApplicationEventMulticaster
listeners.starting();

try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); //事件分析,发布ApplicationEnvironmentPreparedEvent并执行监视器,//onSPplicationEvent方法
Banner printedBanner = this.printBanner(environment);
context = this.createApplicationContext();
new FailureAnalyzers(context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
listeners.finished(context, (Throwable)null);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplica tionLog(), stopWatch);
}

return context;
} catch (Throwable var9) {
this.handleRunFailure(context, listeners, (FailureAnalyzers)analyzers, var9);
throw new IllegalStateException(var9);
}
}
// 环境预处理
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {
ConfigurableEnvironment environment = this.getOrCreateEnvironment(); //创建环境
this.configureEnvironment(environment, applicationArguments.getSourceArgs());//配置环境,包括source及profile
listeners.environmentPrepared(environment);//预处理,包括发布事件
if (this.isWebEnvironment(environment) && !this.webEnvironment) {
environment = this.convertToStandardEnvironment(environment);
}

return environment;
}

// SpringApplicationRunListeners
public void environmentPrepared(ConfigurableEnvironment environment) {
Iterator var2 = this.listeners.iterator();

while(var2.hasNext()) {
SpringApplicationRunListener listener = (SpringApplicationRunListener)var2.next();
listener.environmentPrepared(environment);
}

}

// EventPublishingRunListener 实际发布
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(this.application, this.args, environment));
}

// listener监听,调用监听器onApplicationEvent方法
protected void invokeListener(ApplicationListener listener, ApplicationEvent event) {
ErrorHandler errorHandler = this.getErrorHandler();
if (errorHandler != null) {
try {
listener.onApplicationEvent(event);
} catch (Throwable var7) {
errorHandler.handleError(var7);
}
} else {
try {
listener.onApplicationEvent(event);
} catch (ClassCastException var8) {
String msg = var8.getMessage();
if (msg != null && !msg.startsWith(event.getClass().getName())) {
throw var8;
}

Log logger = LogFactory.getLog(this.getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, var8);
}
}
}
}

//ConfigFileApplicationListener 监听器,这个监听器用来加载配置文件,其他监听器如果监听ApplicationEnvironmentPreparedEvent事件的话,调用其对应的处理逻辑
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent) {
this.onApplicationEnvironmentPreparedEvent((ApplicationEnvironmentPreparedEvent)event);
}

if (event instanceof ApplicationPreparedEvent) {
this.onApplicationPreparedEvent(event);
}

}

以上为springboot加载配置文件逻辑,其中ApplicationEnvironmentPreparedEvent对应事件三大要素中的事件,ApplicationEventMulticaster 类似于事件源,ConfigFileApplicationListener对应其监听器

事件流程【事件源注册监听器】–> 【事件发生,事件源向监听器发送事件】 –> 【事件监听器响应事件】 在此处为ApplicationEventMulticaster 通过反射创建,并注册所有listener,environmentPrepared()方法向listener发布事件,ConfigFileApplicationListener.()方法响应事件

显示 Gitment 评论