java - 用 Switch 打击,降低圈复杂度 java

标签 java oop java-8

在使用 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;
}

在完整的 switch 中有 20 个这样的案例,每个案例中使用不同的消息和不同的变量。 并且某些开关中ifs的深度也达到了3。

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

有什么建议吗?

最佳答案

“使用 enums 代替”,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);
}

关于java - 用 Switch 打击,降低圈复杂度 java,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49690102/

相关文章:

javascript - 使用 Java Selenium WebDriver 获取网页使用的 javascript 的名称

java - Java中如何将数组与数组列表结合起来?

c# - 接口(interface)是数据类型吗?

java - 数据库访问放在哪里

Java 8 - 使用 startsWith 从列表中过滤字符串 X 并将字符串 X 保存到列表

java - 如何从键的 Map<K,V> 和 List<K> 创建 List<T>?

java - 删除 String 中特定的 HTML 标签

java - Spring MVC : @RequestBody when no content-type is specified

javascript - 在类内部声明方法

具有各种操作数的 Java lambda 表达式