繁体   English   中英

重构详细的switch case语句

[英]Refactor a verbose switch case statement

我有一个可以保留单个工厂的天气测量值的对象。

public class FactoryWeather { 

    // each measurement consists of min, max and average observations.
    private Measurement temperature;
    private Measurement humidity;
    private Measurement ...

    public constructor,setters/getters...

}

度量类型定义为如下所示的枚举:

public enum WeatherMeasurementEnum {
    // min and max range of single measurement
    TEMPERATURE(-50,50),
    HUMIDITY(0,100),
    ...

    // validity check for measurements
    public boolean isValid(int average) {
        return average >= minimum && average <= maximum;
    }
}

最后,我使用以下方法更新每个度量:

public void updateWeatherMeasurement(String type, Measurement measurement, FactoryWeather factory) {
    WeatherMeasurementEnum m = WeatherMeasurementEnum(type.toUpperCase());
    if(!m.isValid(measurement.getAverage())
        throw new AppException("Invalid measurement!");

    switch(m) {
    case TEMPERATURE: factory.setTemperature(measurement);break;
    case HUMIDITY: factory.setHumidity(measurement);break;
    ...
    }

}

尽管switch语句看起来不错,但将来的测量类型可能会增加。 考虑到这一点并出于最佳实践的考虑,是否有可能消除这种长开关或if / else语句?

您可以在Map<WeatherMeasurementEnum, Measurement>存储每个枚举实例的度量值,而不是在FactoryWeather中为每个度量值单独创建一个字段。

然后,您只需要做

public void updateWeatherMeasurement(String type, Measurement measurement, FactoryWeather factory) {
    WeatherMeasurementEnum m = WeatherMeasurementEnum(type.toUpperCase());
    if (!m.isValid(measurement.getAverage()) {
        throw new AppException("Invalid measurement!");
    }

    factory.setMeasurement(m, measurement);
}

实际上,由于setMeasurement()方法可以直接验证测量的有效性,因此可以完全消除该方法。

另一个选择是将字段的设置委托给枚举本身:

public enum WeatherMeasurementEnum {
    // min and max range of single measurement
    TEMPERATURE(-50,50) {
        @Override
        setMeasurementInFactoryWeather(Measurement m, FactoryWeather fw) {
            fw.setTemperature(m);
        }
    },
    HUMIDITY(0,100) {
        @Override
        setMeasurementInFactoryWeather(Measurement m, FactoryWeather fw) {
            fw.setHumidity(m);
        }
    },
    ...

    // validity check for measurements
    public boolean isValid(int average) {
        return average >= minimum && average <= maximum;
    }

    public abstract setMeasurementInFactoryWeather(Measurement m, FactoryWeather fw);
}

尽管它看起来比switch语句更冗长,但它具有巨大的优势:引入新的度量类型时,您不会忘记处理度量的设置:编译器将迫使您实现抽象方法。

暂无
暂无

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

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