重构一个详细的switch case语句

时间:2016-08-28 18:25:03

标签: java if-statement switch-statement

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

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(grantResults[0]== PackageManager.PERMISSION_GRANTED){
    Log.v(TAG,"Permission: "+permissions[0]+ "was "+grantResults[0]);
    //resume tasks needing this permission
}

}

测量类型定义为枚举如下:

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

尽管switch语句可能看起来很好,但测量类型将来会增长。考虑到这一点并且为了最佳实践,是否可以消除这种长开关或if / else语句?

1 个答案:

答案 0 :(得分:3)

您可以使用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);
}

事实上,这种方法可以完全消除,因为FactoryWeather的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语句更冗长,但它有一个巨大的优势:当引入新类型的测量时,你无法忘记设置测量:编译器会强制你实现抽象方法