如何使用switch语句为不同的输入类型创建通用方法

问题描述 投票:1回答:3

我正在尝试重构我的代码,因为我创建的方法非常相似。即使是intelliJ也强调它。方法的目的是将(使用switch语句)类型'MessageType'映射到'MessageType',它来自不同的包。问题是switch语句的输入类型也来自不同的包。

private MessageType convertToInsurancePolisyMessageType1 (pl.different.MessageType messageType) {
    switch (messageType) {
        case WARN: return MessageType.WARN;
        case INFO: return MessageType.INFO;
        case ERROR: return MessageType.ERROR;
        default: throw new IllegalArgumentException(messageType.name());
    }
}

private MessageType convertToInsurancePolisyMessageType2 (com.other.MessageType messageType) {
    switch (messageType) {
        case WARNING: return MessageType.WARN;
        case INFO: return MessageType.INFO;
        case ERROR: return MessageType.ERROR;
        default: throw new IllegalArgumentException(messageType.name());
    }
}

有没有简单的方法来重构这个?或者我应该这样离开?

java generics switch-statement refactoring
3个回答
0
投票

我担心没有工作可以在每个输入MessageType和返回的MessageType的值之间进行某种列表/映射。

考虑到名称非常相似,也许您可​​以尝试做一些基于反射的方法......但是我认为如果这些名称发生变化并且如果您经常进行这种转换会导致性能下降,那么除了问题之外什么也不会带来任何问题。

为了补充基于静态映射的其他答案,这是非常好的btw,如果你对代码的控制返回MessageType枚举(即你正在开发这样的枚举)我认为你应该考虑通过重载它来封装转换中的转换每种参数的名称。

这里有几种选择......我个人更喜欢of这个名字。 valueOf是可以接受的,但是因为valueOf(String)会抛出NoSuchElementException,所以你应该保持这种行为。让我们在这里坚持of

enum MessageType {
  WARN, INFO, ERROR;

  private static Map<pl.different.MessageType, MessageType> byPlDiffMType = 
      new EnumMap<>(Map.of(
          pl.different.MessageType.WARN, WARN,
          pl.different.MessageType.INFO, INFO,
          pl.different.MessageType.ERROR, ERROR
      ));

  private static Map<com.other.MessageType, MessageType> byCOthMType = 
      new EnumMap<>(Map.of(
          com.other.MessageType.WARNING, WARN,
          com.other.MessageType.INFO, INFO,
          com.other.MessageType.ERROR, ERROR
      ));

  public static MessageType of(pl.different.MessageType value) {
      return of(byPlDiffMType, value);
  }

  public static MessageType of(com.other.MessageType value) {
      return of(byCOthMType, value);
  }

  private static <V> MessageType of(Map<V, MessageType> map, V value) {
     final MessageType result = map.get(value);
     if (result == null) {
         throw new IllegalArgumentException();
     } else {
         return result;
     }
  }
}

即使你没有对该类源的控制,你可能更好地使用EnumMap而不是常规的Maps(例如HashMap)。

我知道你并没有节省太多的代码......但我认为如果你正在开发它,转换成枚举就有意义封装在枚举类中。

减少线路的唯一方法是通过常用名称进行某种匹配,为那些不同的人添加ifs,但我不鼓励这样做,因为它会随着路上的变化而默默地破坏,并且可能不那么“表现”。


1
投票

好吧,毕竟我没有看到你的切换方法没有坏:)

只是抛出一些替代方案,你可以使用地图:

public class MessageTypeConverter {
    private static final Map<pl.different.MessageType, com.other.MessageType> DIRECT_MAPPING = 
        new EnumMap<pl.different.MessageType, com.other.MessageType>(pl.different.MessageType.class) {{
            put(pl.different.MessageType.WARN, com.other.MessageType.WARN);
            put(pl.different.MessageType.INFO, com.other.MessageType.INFO);
            put(pl.different.MessageType.ERROR, com.other.MessageType.ERROR);
        }}; 
    private static final Map<com.other.MessageType, pl.different.MessageType> REVERSE_MAPPING =
        new EnumMap<com.other.MessageType, pl.different.MessageType>(com.other.MessageType.class) {{
            put(com.other.MessageType.WARN, pl.different.MessageType.WARN);
            put(com.other.MessageType.INFO, pl.different.MessageType.INFO);
            put(com.other.MessageType.ERROR, pl.different.MessageType.ERROR);      
        }};

    private com.other.MessageType convertToInsurancePolisyMessageType1(pl.different.MessageType messageType) {
        return DIRECT_MAPPING.computeIfAbsent(messageType, key -> throw new IllegalArgumentException(messageType.name()));
    }

    private pl.different.MessageType convertToInsurancePolisyMessageType2(com.other.MessageType messageType) {
        return REVERSE_MAPPING.computeIfAbsent(messageType, key -> throw new IllegalArgumentException(messageType.name()));
    }
}


0
投票

像这样的东西(归功于RealSkeptic - 对不起你的评论在我开始写这篇文章后出现了,但同样的事情!):

public class DifferentMessageTypeConverter {
    public enum DifferentMessageType {
        WARNING, INFO, ERROR;
    }

    public enum InsurancePolicyMessageType {
        WARN, INFO, ERROR;
    }

    private static final Map<DifferentMessageType, InsurancePolicyMessageType> DIFF_TO_INS_MAPPING;

    static {
        DIFF_TO_INS_MAPPING = new HashMap<>();
        DIFF_TO_INS_MAPPING.put(DifferentMessageType.WARNING, InsurancePolicyMessageType.WARN);
        DIFF_TO_INS_MAPPING.put(DifferentMessageType.INFO, InsurancePolicyMessageType.INFO);
        DIFF_TO_INS_MAPPING.put(DifferentMessageType.ERROR, InsurancePolicyMessageType.ERROR);
    }

    public InsurancePolicyMessageType convertToInsurancePolisyMessageType1(DifferentMessageType dmt) {
        dmt = Optional.ofNullable(dmt)
                      .orElseThrow(() -> new IllegalArgumentException("dmt must not be null"));

        return Optional.ofNullable(dmt)
                       .map(DIFF_TO_INS_MAPPING::get)
                       .orElseThrow(() -> new IllegalArgumentException(messageType.name()));
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.