Java中的观察者模式

github代码地址:https://github.com/iluwatar/java-design-patterns/tree/master/observer/src/main/java/com/iluwatar/observer

一. 观察者模式原理

观察者模式:定义对象之间的一种一对多依赖关系,使得每当一个对象状态发生改变时,起相关的依赖对象都得到通知并自动更新。

就是说,观察者模式包含被观察者和观察者两类对象,一个被观察者可以被多个观察者观察,一旦被观察者的状态发生改变,所有的观察者都将得到通知。

观察者模式的结构中包含四种角色:

(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)观察者模式只会让观察者知道了被观察者发生了变化的结果,却不知道变化发生的过程。

posted on 2018-10-22 22:32  xctspring  阅读(198)  评论(0编辑  收藏  举报

导航