简体   繁体   English

根据 SOLID 主体注册侦听器

[英]Registering listeners according to SOLID pricipals

I'm practicing oop concepts these days.这些天我正在练习oop概念。 To figure it out I tried the below problem.为了弄清楚,我尝试了以下问题。

There is a sensor monitoring system.有传感器监控系统。 It is a simple system that prints a value, whenever a sensor has picked a value.这是一个简单的系统,只要传感器选择了一个值,它就会打印一个值。

I tried to solve this problem according to oop and SOLID principals.我试图根据oopSOLID原则解决这个问题。

So I created an interface SensorListener所以我创建了一个接口SensorListener

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

Then I created a Sensor class然后我创建了一个Sensor class

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;
    }

}

For sensor types the enum is as below对于传感器类型, enum如下

public enum SensorTypes {
    TEMPERATURE, PH, HUMIDITY;
}

For the monitoring purpose I created a class SensorMonitor that implements SensorListener`出于监控目的,我创建了一个实现SensorMonitor的 class SensorMonitor`

public class SensorMonitor implements SensorListener {

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

}

Finally in the main method I mocked the sensor updated using a Thread ,最后在 main 方法中,我模拟了使用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();

}

In this way program successfully works and prints the output in 3 second intervals.通过这种方式,程序成功运行并以 3 秒的间隔打印 output。

Sensor Name: TEMPERATURE, Measure: 0.0传感器名称:温度,测量:0.0

Sensor Name: HUMIDITY, Measure: 1.0传感器名称:湿度,测量:1.0

Sensor Name: PH, Measure: 2.0传感器名称:PH,测量:2.0

I'm satisfied with the behavior because it does what it says.我对这种行为感到满意,因为它按照它所说的去做。 But I'm not sure whether this a correct oop way of implementing interfaces and whether up to which context is this application scalable.但我不确定这是否是一种正确的oop实现interfaces的方式,以及该应用程序是否可扩展至哪个上下文。

For example as the SensorMonitor how can it know the details of currently operating sensors, and what sensors are in the monitoring process?比如作为SensorMonitor ,它如何知道当前运行的传感器的详细信息,以及监控过程中有哪些传感器?

Can someone point out what are the pros and cons in my approach.有人可以指出我的方法的优缺点。

Is this conforms to SOLID principals?这符合 SOLID 原则吗?

I appreciate a more concise approach for this problem.我很欣赏这个问题的更简洁的方法。

There's no way to tell whether a design is good or bad if there's no specific requirements.如果没有具体要求,就无法判断一个设计是好是坏。 If you just wanted to be able to listen to new sensor values then your current design works.如果您只是想能够听到新的传感器值,那么您当前的设计就可以了。

One thing that's certainly flawed is that registerListener overrides the previous listener (if any) so that could have unexpected results from the client perspective: setListener would probably have made it more clear that's the expected behavior or throw an exception if registerListener is called more than once if it doesn't support more than one registration.肯定有缺陷的一件事是registerListener覆盖了以前的侦听器(如果有的话),因此从客户端的角度来看可能会产生意想不到的结果: setListener可能会更清楚地说明这是预期的行为,或者如果多次调用registerListener则抛出异常如果它不支持多个注册。

For example as the SensorMonitor how can it know the details of currently operating sensors, and what sensors are in the monitoring process?比如作为 SensorMonitor,它如何知道当前运行的传感器的详细信息,以及监控过程中有哪些传感器?

Well obviously your design fails at solving this problem since the SensorMonitor isn't modeled as such and acts more simply as an independent "listener".很明显,您的设计未能解决这个问题,因为SensorMonitor没有像这样建模,而是更简单地充当独立的“侦听器”。 You'd simply have to adapt your SensorMonitor concept for the new requirements.您只需根据新要求调整您的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);
    }

}

Now you could make the monitor more flexible by allowing to instantiate it with a SensorListener and you could implement a CompositeSensorListener to merge multiple listeners together, etc.现在,您可以通过允许使用SensorListener对其进行实例化来使监视器更加灵活,并且您可以实现CompositeSensorListener以将多个侦听器合并在一起,等等。

Like I said there's no good nor bad design when there's no specific problem to solve .就像我说的,当没有具体问题需要解决时,没有好坏的设计

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM