#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
для объединения нескольких прослушивателей вместе и т. Д.
Как я уже сказал, нет ни хорошего, ни плохого дизайна, когда нет конкретной проблемы, которую нужно решить.