Статьи

Поведенческие модели дизайна: Наблюдатель

Observer — один из самых популярных шаблонов проектирования. Он часто использовался во многих случаях использования программного обеспечения, поэтому многие языки предоставляют его как часть своей стандартной библиотеки.

Используя шаблон наблюдателя, мы можем решить следующие задачи.

  • Зависимость от объектов, определенных таким образом, чтобы избежать жесткой связи
  • Изменения в объекте изменяют его зависимые объекты
  • Объект может уведомить все свои зависимые объекты

Представьте себе сценарий устройства с несколькими датчиками. Некоторые части кода должны будут получать уведомления о поступлении новых данных с датчиков и, соответственно, действовать соответствующим образом. Мы начнем с простого класса, который представляет данные json.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
package com.gkatzioura.design.behavioural.observer;
 
public class SensorData {
 
    private final String sensor;
    private final Double measure;
 
    public SensorData(String sensor, Double measure) {
        this.sensor = sensor;
        this.measure = measure;
    }
 
    public String getSensor() {
        return sensor;
    }
 
    public Double getMeasure() {
        return measure;
    }
}

Мы создадим интерфейс наблюдателя. Каждый класс, который реализует интерфейс наблюдателя, должен быть уведомлен, как только новый объект создан.

1
2
3
4
5
6
7
package com.gkatzioura.design.behavioural.observer;
 
public interface Observer {
 
    void update(SensorData sensorData);
 
}

Следующим шагом является создание наблюдаемого интерфейса. Наблюдаемый интерфейс будет иметь методы для регистрации наблюдателей, которые должны получать уведомления.

01
02
03
04
05
06
07
08
09
10
11
package com.gkatzioura.design.behavioural.observer;
 
public interface Observable {
 
    void register(Observer observer);
 
    void unregister(Observer observer);
 
    void updateObservers();
 
}

Теперь давайте добавим несколько реализаций.
Слушатель датчика получит данные от датчиков и уведомит наблюдателей о наличии данных.

01
02
03
04
05
06
07
08
09
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
package com.gkatzioura.design.behavioural.observer;
 
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
 
public class SensorReceiver implements Observable {
 
    private List data = new ArrayList();
    private List observers = new ArrayList();
 
    @Override
    public void register(Observer observer) {
        observers.add(observer);
    }
 
    @Override
    public void unregister(Observer observer) {
        observers.remove(observer);
    }
 
    public void addData(SensorData sensorData) {
        data.add(sensorData);
    }
 
    @Override
    public void updateObservers() {
 
        /**
         * The sensor receiver has retrieved some sensor data and thus it will notify the observer
         * on the data it accumulated.
         */
 
        Iterator iterator = data.iterator();
 
        while (iterator.hasNext()) {
 
            SensorData sensorData = iterator.next();
 
            for(Observer observer:observers) {
                observer.update(sensorData);
            }
 
            iterator.remove();
        }
    }
 
}

Мы создадим наблюдателя, который будет регистрировать данные датчика, полученные в базу данных, это может быть приток или упругий поиск, который вы назовете.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.gkatzioura.design.behavioural.observer;
 
public class SensorLogger implements Observer {
 
    @Override
    public void update(SensorData sensorData) {
 
        /**
         * Persist data to the database
         */
 
        System.out.println(String.format("Received sensor data %s: %f",sensorData.getSensor(),sensorData.getMeasure()));
    }
 
}

Давайте сложим все вместе.

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.gkatzioura.design.behavioural.observer;
 
public class SensorMain {
 
    public static void main(String[] args) {
 
        SensorReceiver sensorReceiver = new SensorReceiver();
        SensorLogger sensorLogger = new SensorLogger();
        sensorReceiver.register(sensorLogger);
        sensorReceiver.addData(new SensorData("temperature",1.2d));
        sensorReceiver.updateObservers();
    }
}

Вы можете найти исходный код на github .

Опубликовано на Java Code Geeks с разрешения Эммануила Гкациоураса, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Поведенческие шаблоны дизайна: Наблюдатель

Мнения, высказанные участниками Java Code Geeks, являются их собственными.