【问题标题】:Refactoring instanceof重构 instanceof
【发布时间】:2021-12-27 18:00:50
【问题描述】:

在我当前的项目中,我需要在仅在运行时知道的类型之间转换值:输入类型是输入的 JSON 类型,输出类型在运行时加载的配置文件中定义。

我想出了一个通用的解决方案,但我对它不太满意,因为支持新的输入类型意味着您需要更改现有支持的输出类型类(这违反了开/关原则),我使用很多instanceof 和很多演员。

在可维护性方面,有没有比我做的更好的解决方案?


我试图获得一种我的代码的最小示例,所以这里是:

package org.example.scratch;

import static java.lang.Float.*;
import static java.lang.Integer.*;

import java.time.LocalDate;
import java.time.ZonedDateTime;

import lombok.Value;

class Scratch {
    public static void main(String[] args) {
        // runtime values
        final FieldValue value = StringValue.of("3.14"); // input value
        final Converter<?> converter = FloatConverter.of(); // output type

        Mapper<?> mapper = Mapper.of(converter);
        FieldValue converted = mapper.convert(value);
        System.out.println(converted);
    }

    @Value(staticConstructor = "of")
    static class Mapper<T extends FieldValue> {
        Converter<T> converter;

        public T convert(FieldValue value) {
            return converter.apply(value);
        }
    }

    interface Converter<T extends FieldValue> {
        T apply(FieldValue value);
    }

    @Value(staticConstructor = "of")
    static class IntegerConverter implements Converter<IntegerValue> {
        @Override
        public IntegerValue apply(FieldValue value) {
            if (value instanceof IntegerValue) {
                return (IntegerValue) value;
            }

            if (value instanceof FloatValue) {
                return IntegerValue.of(((FloatValue) value).getValue().intValue());
            }

            if (value instanceof StringValue) {
                return IntegerValue.of(parseInt(((StringValue) value).getValue()));
            }

            throw new IllegalArgumentException("Impossible to convert a " + value.getClass().getName() + " to a " + IntegerValue.class.getSimpleName());
        }
    }

    @Value(staticConstructor = "of")
    static class FloatConverter implements Converter<FloatValue> {
        @Override
        public FloatValue apply(FieldValue value) {
            if (value instanceof FloatValue) {
                return (FloatValue) value;
            }

            if (value instanceof IntegerValue) {
                return FloatValue.of(((IntegerValue) value).getValue().floatValue());
            }

            if (value instanceof StringValue) {
                return FloatValue.of(parseFloat(((StringValue) value).getValue()));
            }

            throw new IllegalArgumentException("Impossible to convert a " + value.getClass().getName() + " to a " + FloatValue.class.getSimpleName());
        }
    }

    @Value(staticConstructor = "of")
    static class DateConverter implements Converter<DateValue> {
        @Override
        public DateValue apply(FieldValue value) {
            if (value instanceof DateValue) {
                return (DateValue) value;
            }

            if (value instanceof StringValue) {
                return DateValue.of(LocalDate.parse(((StringValue) value).getValue()));
            }

            throw new IllegalArgumentException("Impossible to convert a " + value.getClass().getName() + " to a " + DateValue.class.getSimpleName());
        }
    }

    @Value(staticConstructor = "of")
    static class TimestampConverter implements Converter<TimestampValue> {
        @Override
        public TimestampValue apply(FieldValue value) {
            if (value instanceof TimestampValue) {
                return (TimestampValue) value;
            }

            if (value instanceof StringValue) {
                return TimestampValue.of(ZonedDateTime.parse(((StringValue) value).getValue()));
            }

            throw new IllegalArgumentException("Impossible to convert a " + value.getClass().getName() + " to a " + TimestampValue.class.getSimpleName());
        }
    }

    interface FieldValue {}

    @Value(staticConstructor = "of")
    static class IntegerValue implements FieldValue {
        Integer value;
    }

    @Value(staticConstructor = "of")
    static class FloatValue implements FieldValue {
        Float value;
    }

    @Value(staticConstructor = "of")
    static class DateValue implements FieldValue {
        LocalDate value;
    }

    @Value(staticConstructor = "of")
    static class TimestampValue implements FieldValue {
        ZonedDateTime value;
    }

    @Value(staticConstructor = "of")
    static class StringValue implements FieldValue {
        String value;
    }
}

【问题讨论】:

    标签: java generics refactoring instanceof maintainability


    【解决方案1】:

    如果可维护性是您的目标,那么我认为您可以将一些东西组合在一起以保持简单和易于更改。请注意 - 我删除了 Lombok,因为我无法让它在我的机器上运行。我还删除了静态功能,因为您的用例似乎不需要。

    通用值

    public abstract class GenericValue<T>
    {
    
       private T value;
       
       public GenericValue(T value)
       {
       
          this.value = value;
       
       }
    
       public GenericValue(GenericValue<?> value)
       {
       
          this.value = convert(value);
       
       }
    
       public T getValue()
       {
       
          return this.value;
       
       }
       
       public abstract T convert(GenericValue<?> inputType);
    
       public static void main(String[] args)
       {
       
          GenericValue<String> input = new StringValue("123"); // input value
          
          {
          
             GenericValue<Float> output = new FloatValue(input);
          
             Float result = output.getValue();
          
             System.out.println(result);
          
          }
          
          {
          
             GenericValue<Integer> output = new IntegerValue(input);
          
             Integer result = output.getValue();
          
             System.out.println(result);
          
          }
          
       }
    
    }
    
    

    ~

    整数值

    public class IntegerValue extends GenericValue<Integer>
    {
    
       public IntegerValue(Integer value)
       {
          super(value);
       }
       
       public IntegerValue(GenericValue<?> value)
       {
          super(value);
       }
       
       public Integer convert(GenericValue<?> inputType)
       {
       
          if (inputType instanceof IntegerValue)
          {
          
             IntegerValue temp = ((IntegerValue) inputType);
          
             return (temp.getValue());
          
          }
          
          else if (inputType instanceof StringValue)
          {
          
             StringValue temp = (StringValue) inputType;
          
             return (Integer.parseInt(temp.getValue()));
          
          }
          
          else if (inputType instanceof FloatValue)
          {
          
             FloatValue temp = (FloatValue) inputType;
          
             return (temp.getValue().intValue());
          
          }
          
          else
          {
          
             throw new IllegalArgumentException("Impossible to convert a " + inputType.getClass().getName() + " to " + this.getClass().getSimpleName());
          
          }
          
       }
    
    }
    

    ~

    浮点值

    public class FloatValue extends GenericValue<Float>
    {
    
       public FloatValue(Float value)
       {
          super(value);
       }
    
       public FloatValue(GenericValue<?> value)
       {
          super(value);
       }
       
       public Float convert(GenericValue<?> inputType)
       {
       
          if (inputType instanceof IntegerValue)
          {
          
             IntegerValue temp = (IntegerValue) inputType;
          
             return Float.valueOf(temp.getValue().floatValue());
          
          }
          
          else if (inputType instanceof StringValue)
          {
          
             StringValue temp = (StringValue) inputType;
          
             return Float.parseFloat(temp.getValue());
          
          }
          
          else if (inputType instanceof FloatValue)
          {
          
             FloatValue temp = (FloatValue) inputType;
          
             return temp.getValue();
          
          }
          
          else
          {
          
             throw new IllegalArgumentException("Impossible to convert a " + inputType.getClass().getName() + " to " + this.getClass().getSimpleName());
          
          }
       
       }
    
    }
    

    ~

    字符串值

    public class StringValue extends GenericValue<String>
    {
    
       public StringValue(String value)
       {
          super(value);
       }
    
       public StringValue(GenericValue<?> value)
       {
          super(value);
       }
    
       public String convert(GenericValue<?> inputType)
       {
       
          if (inputType instanceof IntegerValue || inputType instanceof FloatValue || inputType instanceof StringValue)
          {
          
             String string = String.valueOf(inputType.getValue());
          
             return (string);
          
          }
          
          else
          {
          
             throw new IllegalArgumentException("Impossible to convert a " + inputType.getClass().getName() + " to " + this.getClass().getSimpleName());
          
          }
          
       }
    
    }
    

    ~

    日期值

    import java.time.LocalDate;
    
    public class DateValue extends GenericValue<LocalDate>
    {
    
       public DateValue(LocalDate value)
       {
          super(value);
       }
    
       public DateValue(GenericValue<?> value)
       {
          super(value);
       }
       
       public LocalDate convert(GenericValue<?> inputType)
       {
       
          if (inputType instanceof StringValue)
          {
          
             StringValue temp = ((StringValue) inputType);
          
             return LocalDate.parse(temp.getValue());
          
          }
          
          else if (inputType instanceof DateValue)
          {
          
             DateValue temp = (DateValue) inputType;
          
             return temp.getValue();
          
          }
          
          else
          {
          
             throw new IllegalArgumentException("Impossible to convert a " + inputType.getClass().getName() + " to " + this.getClass().getSimpleName());
          
          }
       
       }
    
    }
    

    ~

    时间戳值

    import java.time.ZonedDateTime;
    
    public class TimestampValue extends GenericValue<ZonedDateTime>
    {
    
       public TimestampValue(ZonedDateTime value)
       {
          super(value);
       }
    
       public TimestampValue(GenericValue<?> value)
       {
          super(value);
       }
       
       public ZonedDateTime convert(GenericValue<?> inputType)
       {
       
          if (inputType instanceof StringValue)
          {
          
             StringValue temp = ((StringValue) inputType);
          
             return ZonedDateTime.parse(temp.getValue());
          
          }
          
          else if (inputType instanceof TimestampValue)
          {
          
             TimestampValue temp = (TimestampValue) inputType;
          
             return temp.getValue();
          
          }
          
          else
          {
          
             throw new IllegalArgumentException("Impossible to convert a " + inputType.getClass().getName() + " to " + this.getClass().getSimpleName());
          
          }
       
       }
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 1970-01-01
      • 2013-01-12
      • 2019-08-29
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      相关资源
      最近更新 更多