Регистрация слушателей в соответствии с ТВЕРДЫМИ принципами

#java #oop #interface #solid-principles

Вопрос:

В эти дни я практикуюсь oop в концепциях. Чтобы разобраться в этом, я попробовал решить приведенную ниже проблему.

Существует система мониторинга датчиков. Это простая система, которая выводит значение всякий раз, когда датчик выбирает значение.

Я попытался решить эту проблему в соответствии с oop принципами и SOLID принципами.

Поэтому я создал интерфейс SensorListener

 interface SensorListener{
    public void onValueUpdated(SensorTypes type, double value);
}
 

Затем я создал Sensor класс

 public class Sensor {

    private int value;
    private SensorTypes types;
    private SensorListener sensorListener;

    public Sensor(SensorTypes types) {
        this.types = types;
    }

    public void setValue(int value) {
        this.value = value;
        sensorListener.onValueUpdated(types, value);
    }

    public void registerListener(SensorListener sensorListener) {
        this.sensorListener = sensorListener;
    }

}
 

Для типов датчиков enum это выглядит следующим образом

 public enum SensorTypes {
    TEMPERATURE, PH, HUMIDITY;
}
 

Для целей мониторинга я создал класс SensorMonitor , реализующий SensorListener`

 public class SensorMonitor implements SensorListener {

    @Override
    public void onValueUpdated(SensorTypes type, double value) {
        System.out.println("Sensor Name: "   type   ", Measure: "   value);
    }

}
 

Наконец, в основном методе я издевался над датчиком, обновленным с помощью Thread ,

 public static void main(String[] args) {

    SensorMonitor sensorMonitor = new SensorMonitor();
    Sensor temperature = new Sensor(SensorTypes.TEMPERATURE);
    temperature.registerListener(sensorMonitor);
    Sensor humidity = new Sensor(SensorTypes.HUMIDITY);
    humidity.registerListener(sensorMonitor);
    Sensor pH = new Sensor(SensorTypes.PH);
    pH.registerListener(sensorMonitor);
    Thread thread = new Thread(() -> {
        int i = 0;
        while (true) {
            try {
                temperature.setValue(i  );
                Thread.sleep(3000);
                humidity.setValue(i  );
                Thread.sleep(3000);
                pH.setValue(i  );
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                System.out.println("thread interrupted");
            }
        }
    });

    thread.start();

}
 

Таким образом, программа успешно работает и выводит результат с интервалом в 3 секунды.

Название датчика: ТЕМПЕРАТУРА, Измерение: 0,0

Название датчика: ВЛАЖНОСТЬ, Измерение: 1,0

Название датчика: PH, Измерение: 2,0

Я доволен его поведением, потому что он делает то, что говорит. Но я не уверен, является ли это правильным oop способом реализации interfaces и масштабируется ли это приложение в зависимости от контекста.

Например SensorMonitor , как он может узнать детали работающих в настоящее время датчиков и какие датчики находятся в процессе мониторинга?

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

Соответствует ли это ТВЕРДЫМ принципам?

Я ценю более лаконичный подход к этой проблеме.

Комментарии:

1. Возможно, вы подумаете о том, чтобы опубликовать свой вопрос в обзоре кода .

2. Забыл этот вопрос?

Ответ №1:

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

Одна вещь, которая, безусловно, ошибочна, заключается в том, что registerListener переопределяет предыдущий прослушиватель (если таковой имеется), что может привести к неожиданным результатам с точки зрения клиента: setListener вероятно, было бы более ясно, что это ожидаемое поведение или исключение, если registerListener вызывается более одного раза, если оно не поддерживает более одной регистрации.

Например, как сенсомонитор, как он может знать детали работающих в настоящее время датчиков и какие датчики находятся в процессе мониторинга?

Ну, очевидно, что ваш дизайн не справляется с решением этой проблемы, поскольку SensorMonitor он не моделируется как таковой и действует более просто как независимый «слушатель». Вам просто придется адаптировать свою SensorMonitor концепцию к новым требованиям.

 public class SensorMonitor implements SensorListener {
    private final Set<Sensor> sensors;

    public SensorMonitor() {
        sensors = new HashSet<>();
    }

    public void startMonitoring(Sensor sensor) {
        sensors.add(sensor);

        // Note that Current `registerListener` implementation could break the monitor
        // since you could override the monitor's listener.
        sensor.registerListener(this);
    }

    public Set<Sensor> monitoredSensors() {
        return Collections.unmodifiableSet(sensors);
    }

    @Override
    public void onValueUpdated(SensorTypes type, double value) {
        System.out.println("Sensor Name: "   type   ", Measure: "   value);
    }

}
 

Теперь вы можете сделать монитор более гибким, разрешив создать его экземпляр с помощью a SensorListener , и вы можете реализовать a CompositeSensorListener для объединения нескольких прослушивателей вместе и т. Д.

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