一. 观察者模式原理
观察者模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,起相关的依赖对象都得到通知并自动更新。
就是说,观察者模式包含被观察者和观察者两类对象,一个被观察者可以被多个观察者观察,一旦被观察者的状态发生改变,所有的观察者都将得到通知。
观察者模式的结构中包含四种角色:
(1)主题(Subject):主题是一个接口,该接口规定了具体主题需要实现的方法,比如,添加、删除观察者以及通知观察者更新数据的方法。
(2)观察者(Observer):观察者是一个接口,该接口规定了具体观察者用来更新数据的方法。
(3)具体主题(ConcreteSubject):具体主题是实现主题接口类的一个实例,该实例包含有可以经常发生变化的数据。具体主题需使用一个集合,比如ArrayList,存放观察者的引用,以便数据变化时通知具体观察者。
(4)具体观察者(ConcreteObserver):具体观察者是实现观察者接口类的一个实例。具体观察者包含有可以存放具体主题引用的主题接口变量,以便具体观察者让具体主题将自己的引用添加到具体主题的集合中,使自己成为它的观察者,或让这个具体主题将自己从具体主题的集合中删除,使自己不再是它的观察者。
二. 观察者模式的具体应用
1.观察者
(1)观察者的抽象
WeatherObserver类是所有观察者的抽象,观察者可以通过实现它来创建观察者,被观察者的抽象就是观察者模式结构中的Observer角色。
1 package com.iluwatar.observer;
2
3 /**
4 *
5 * Observer interface.
6 *
7 */
8 public interface WeatherObserver {
9
10 void update(WeatherType currentWeather);
11
12 }
(2)具体观察者
Oscr类和Hobbits类是作为具体的观察者,观察的是Weather类,接受Weather类的通知,具体观察者就是观察者模式中的ConcreteObserver角色。
1 /**
2 *
3 * Hobbits
4 *
5 */
6 public class Hobbits implements WeatherObserver {
7
8 private static final Logger LOGGER = LoggerFactory.getLogger(Hobbits.class);
9
10 @Override
11 public void update(WeatherType currentWeather) {
12 switch (currentWeather) {
13 case COLD:
14 LOGGER.info("The hobbits are shivering in the cold weather.");
15 break;
16 case RAINY:
17 LOGGER.info("The hobbits look for cover from the rain.");
18 break;
19 case SUNNY:
20 LOGGER.info("The happy hobbits bade in the warm sun.");
21 break;
22 case WINDY:
23 LOGGER.info("The hobbits hold their hats tightly in the windy weather.");
24 break;
25 default:
26 break;
27 }
28 }
29 }
1 /**
2 *
3 * Orcs
4 *
5 */
6 public class Orcs implements WeatherObserver {
7
8 private static final Logger LOGGER = LoggerFactory.getLogger(Orcs.class);
9
10 @Override
11 public void update(WeatherType currentWeather) {
12 switch (currentWeather) {
13 case COLD:
14 LOGGER.info("The orcs are freezing cold.");
15 break;
16 case RAINY:
17 LOGGER.info("The orcs are dripping wet.");
18 break;
19 case SUNNY:
20 LOGGER.info("The sun hurts the orcs' eyes.");
21 break;
22 case WINDY:
23 LOGGER.info("The orc smell almost vanishes in the wind.");
24 break;
25 default:
26 break;
27 }
28 }
29 }
2. 被观察者
这里是只考虑了唯一一个被观察者,没有考虑被观察者的多个是实现,所以直接实现了被观察者观察者,也就是将观察者模式中的Subject和ConcreteSubject角色合并了。
1 public class Weather {
2
3 private static final Logger LOGGER = LoggerFactory.getLogger(Weather.class);
4
5 private WeatherType currentWeather;
6 private List<WeatherObserver> observers;
7
8 public Weather() {
9 observers = new ArrayList<>();
10 currentWeather = WeatherType.SUNNY;
11 }
12
13 public void addObserver(WeatherObserver obs) {
14 observers.add(obs);
15 }
16
17 public void removeObserver(WeatherObserver obs) {
18 observers.remove(obs);
19 }
20
21 /**
22 * Makes time pass for weather
23 */
24 public void timePasses() {
25 WeatherType[] enumValues = WeatherType.values();
26 currentWeather = enumValues[(currentWeather.ordinal() + 1) % enumValues.length];
27 LOGGER.info("The weather changed to {}.", currentWeather);
28 notifyObservers();
29 }
30
31 private void notifyObservers() {
32 for (WeatherObserver obs : observers) {
33 obs.update(currentWeather);
34 }
35 }
36 }
三. 观察者模式的优缺点
1. 优点
(1)观察者模式定义了稳定的消息更新传递机制,可以实现一对多的广播通信。
(2)观察者模式在被观察者和观察者之间建立的关系并不是很紧密,它们是不同的抽象,符合“低耦合”的系统设计理念
2. 缺点
(1)观察者模式建立的消息传递机制是低效的,如果建立了多个观察者,可能会影响消息传递的时间。
(2)观察者模式只会让观察者知道了被观察者发生了变化的结果,却不知道变化发生的过程。