结合if子句重构大开关大小写



所以我有这样的东西:

switch (data){
case "one" :
if (version1) 
createDataOneV1();
else 
createDataOnetV2();
break;
case "two":
if(version1)
createDataTwoV1();
else 
createDataTwoV2();
break;
default:
createDefaultData();
}

有很多(切换(案例。有重构的建议吗?

不要使用Map。它不会为您提供与switch相同的编译时安全性。

如果你仍然想摆脱它,那么我建议使用enum:

public enum DataCreationStrategy {
ONE("one", DataCreator::createDataOneV1, DataCreator::createDataOneV2),
TWO("two", DataCreator::createDataTwoV1, DataCreator::createDataTwoV2)
// ... other cases
;
private final String key;
private final Function<DataCreator, String> creator;
private final Function<DataCreator, String> defaultCreator;
DataCreationStrategy(String key, Function<DataCreator, String> creator, Function<DataCreator, String> defaultCreator) {
this.key = key;
this.creator = creator;
this.defaultCreator = defaultCreator;
}
public static Function<DataCreator, String> of(String key, boolean flag) {
for (DataCreationStrategy strategy: values()){
if(strategy.key.equals(key)){
return flag ? strategy.creator : strategy.defaultCreator;
}
}
return DataCreator::createDefaultData;
}
}

然后这样使用:

String createdData = DataCreationStrategy.of(key, versionFlag).apply(creator);

(您可以将String替换为需要生成的实际数据类型(


of方法也可以用Stream API方式实现。但在这种特殊情况下,普通的旧for循环要干净得多。

public static Function<DataCreator, String> of(String key, boolean flag) {
return Arrays.stream(values())
.filter(s -> s.key.equals(key))
.findAny()
.map(s -> flag ? flag ? s.creator : s.defaultCreator )
.orElse(DataCreator::createDefaultData);
}

创建以字符串为键、函数为值的Map。

您可以用一些SupplierHashMap创建Key(例如(:

@RequiredArgsConstructor
class SpecialKey  {
private final String data;
private final boolean second;
// hashCode/equals
}

假设您的createDataOneV1createDataOneV2返回boolean:

Map<SpecialKey, Supplier<Boolean>> map = new HashMap<>();
map.put(new SpecialKey("one", true), this::createDataOneV1);
map.put(new SpecialKey("one", false), this::createDataOneV2);

然后简单地说:

String data = ... // get the "data" somehow
boolean version = ...
boolean res = map.getOrDefault(new SpecialKey(data, version), this::createDefaultData).get();

首先决定是否真的需要重构代码。它丑吗?当然但它简单明了。您可以使用一个额外的抽象层来清理它,但这通常是以使代码不那么明显和性能降低为代价的。

无论如何,如果你想重构代码,你可以使用类型系统。定义一个DataCreator接口,可以为V1V2生成数据。您可以使用以下函数选择正确的DataCreator

DataCreator getDataCreatorForData(String data){
switch(data) {
case "one": return new DataCreatorOne();
case "two": return new DataCreatorTwo();
default: return new DefaultDataCreator()
}
}

一旦你有了DataCreator,你就可以检查版本:

DataCreator creator = getDataCreatorForData(data);
if (version1){
creator.createV1Data();
}else{
creator.createV2Data();
}

这个结构比问题中的结构更平坦,嵌套更少。

最新更新