使用Switch,减少圈复杂度java

在使用java时我遇到了一个奇怪的情况,让我们先从代码开始。

public static String constructMessage(final String reason, final String xId, final String yId, final IonStruct metadataStruct) throws DataSanityException { String message = ""; switch (reason) { case "NOT_ACTIVE": if (xId != null) { message = String.format("Y %s X %s not active: status is inactive%n", yId, xId); } else { message = String.format("Y %s not active: status is inactive%n", yId); } break; case "PRICE_GONE": if (metadataStruct.containsKey("applied")) { final String applied = metadataStruct.get("applied"); if (applied.equals("single")) { message = String.format("X %s is not active. price for the X is gone. " + "Y price %s for an X should not be gone by %s.%n", xId, metadataStruct.get("yPrice"), metadataStruct.get("zPrice")); } else { if (metadataStruct.get("gonePeriod").equals("gonegone")) { message = String.format("Y price is %s whereas the gone price is %s." + " Y price for an X should be at least %s%% lower than gone.%n", metadataStruct.get(yPrice), metadataStruct.get(zPrice), metadataStruct.get("xyzPrice")); } else { message = String.format("Y price %s for an X should be at least %s%% lower than gone price %s in last %s days.%n", metadataStruct.get(yPrice), metadataStruct.get("mpqPrice"), metadataStruct.get(lpzPrice), metadataStruct.get("numberOfDays")); } } } else { message = String.format( "X %s in Y %s is not active. is %s%%, min mpux is %s%%. ", xId, yId, metadataStruct.get("lpux"), metadataStruct.get("mpxPrice")); } break; and so on ----------- around 20 cases. default: message = ""; break; } 

在完整的开关中有20个这样的情况,每个情况下使用不同的消息和不同的变量。 在某些交换机中,ifs的深度也达到3。

因此,圈复杂度将达到29(太高),所以我想重构具有低圈复杂度和更好可读性的代码。

有什么建议吗?

来自Martin Fowler的重构书 在此处输入图像描述

我可以建议以下重构方法:

 import java.util.HashMap; import java.util.Map; public class Refactoring { private static class IonStruct {}; private static interface MessageBuilder { String build(final String xId,final String yId, final IonStruct metadataStruct); } private static class NotActiveMessageBuilder implements MessageBuilder { private static final String YX_NON_ACTIVE_FMT = "Y %s X %s not active: status is inactive%n;"; private static final String Y_NON_ACTIVE_FMT = "Y %s not active: status is inactive%n"; @Override public String build(String xId, String yId, IonStruct metadataStruct) { return (xId != null) ? String.format(YX_NON_ACTIVE_FMT, yId, xId) : String.format(Y_NON_ACTIVE_FMT, yId) ; } } private static enum MessageTypeChine { instance(); private final Map builders; private MessageTypeChine() { this.builders = new HashMap<>(); this.builders.put("NOT_ACTIVE", new NotActiveMessageBuilder()); } public String constructMessage(final String reason, final String xId, final String yId, final IonStruct metadataStruct) { MessageBuilder builder = this.builders.get(reason); if(null != builder) return builder.build(xId, yId, metadataStruct); throw new UnsupportedOperationException("Message type is not supported"); } } public static String constructMessage(final String reason, final String xId, final String yId, final IonStruct metadataStruct) { return MessageTypeChine.instance.constructMessage(reason, xId, yId, metadataStruct); } } 

使用“使用enum s”,Kayaman意味着:

 interface MessageGenerator { String getMessage(String xId, String yId, IonStruct metadataStruct); } enum Reason implements MessageGenerator { NOT_ACTIVE((xId, yId, unused) -> (xId != null) ? String.format("Y %s X %s not active: status is inactive%n", yId, xId) : String.format("Y %s not active: status is inactive%n", yId) }), PRICE_GONE(...), DEFAULT(xId, yId, metadataStruct) -> String.format("X %s in Y %s is not active. is %s%%, min mpux is %s%%. ", xId, yId, metadataStruct.get("lpux"), metadataStruct.get("mpxPrice"))); private MessageGenerator delegate; private Reason(MessageGenerator delegate) { this.delegate = delegate; } // implement MessageGenerator interface by delegation public String getMessage(String xId, String yId, IonStruct metadataStruct) { return delegate.getMessage(xId, yId, metadataStruct); } public static Reason findReason(String reason) { Reason result = DEFAULT; try { result = valueOf(reason); } catch (RuntimeException ex) {} return result; } } 

你可以做到

 String constructMessage(String reason, final String xId, final String yId, final IonStruct metadataStruct) { Reason r = Reason.findReason(reason); return r.getMessage(xId, yId, metadataStruct); }