重构条件

Refactoring conditionals

我必须根据某些条件输出文本,如何重构它以使其易于理解和维护?

如果最好的选择是用状态替换,我需要为每个枚举组合创建一个 class?

public enum CalcType {A, B, C, D}
public enum LicensingOption {HOME, PRO, ULTIMATE}

public void printHeader() {
    switch (calc) {
        case A:
            printHeaderX();
            break;
        case B:
            printHeaderY();
            break;
        default:
            printHeaderByLicensingOption();
    }
}

public void printHeaderByLicensingOption() {
    switch (license) {
        case PRO:
            printHeaderW();
            break;
        case HOME:
            printHeaderZ();
            break;
        case ULTIMATE:
            printHeaderA();
            break;
    }
}

public void printFooter() {
    if (calc.equals(CalcType.A))
        printFooterX();
    else
        printFooterByLicensingOption();
}

public void printFooterByLicensingOption() {
    switch (license){
        case PRO:
            printFooterW();
            break;
        case HOME:
            printFooterZ();
            break;
        case ULTIMATE:
            printFooterA();
            break;
    }
}

public void printFooterW(){
    if (calc.equals(CalcType.B))
        printW1();
    else
        printW2();
}

这是一个完美的例子,说明 State 模式有助于管理代码的复杂性,特别是如果您将来要添加其他 LicensingOption 和 CalcType。

This pattern is used in computer programming to encapsulate varying behavior for the same object based on its internal state. This can be a cleaner way for an object to change its behavior at runtime without resorting to large monolithic conditional statements and thus improve maintainability.

我在下面附上了针对您的案例的状态模式实施示例,但请注意,您的代码示例很难真正给您好的建议(printW1printHeaderZprintHeaderA 并没有真正给我那么多关于你的域的信息),但我尽力给你一些与你提供的代码等效的东西。您可能希望将某些行为从 CalcType 移至 LicesingOption,因为我不清楚这两种状态如何在您的应用程序中相互交互。

配置

// Whatever way you decide to get that configuration
public CalcType calcType = Config.CalcTypen 
public LicensingOption license = Config.LicensingOption

计算类型类

abstract class CalcType {
    public void printHeader() {
        // Default behavior of printHeader() is printHeaderByLicensingOption(); 
        //  except for CalcTypeA and CalcTypeB, so we are going to redefine them in CalcTypeA and CalcTypeB.
        license.printHeaderByLicensingOption()
    }

    public void printFooter() {
        // Default behavior of printFooter() is printFooterByLicensingOption(); 
        //  except for CalcTypeA, so we are going to redefine it in CalcTypeA.
        license.printFooterByLicensingOption()
    }

    public void printFooterW() {
        // Default behavior of printFooterW() is printW2(); 
        //  except for CalcTypeB, so we are going to redefine it in CalcTypeB.
        printW2();
    }
}

class CalcTypeA extends CalcType {
    public void printHeader() {
        printHeaderX()
    }

    public void printFooter() {
        printFooterX()
    }
}

class CalcTypeB extends CalcType {
    public void printHeader() {
        printHeaderY()
    }

    public void printFooterW() {
        printW1();
    }
}

许可选项类

abstract class LicensingOption {
    // Those methods all have very different behaviour and it's hard from you example to know if there is any "default". 
    // Assuming there is none, just declare them abstract and define them in subclasses only.
    abstract public void printHeaderByLicensingOption();
    abstract public void printFooterByLicensingOption();
}

class ProLicense {
    public void printHeaderByLicensingOption() {
        printHeaderW();
    }

    public void printFooterByLicensingOption() {
        calcType.printFooterW()
    }
}

class HomeLicense {
    public void printHeaderByLicensingOption() {
        printHeaderZ();
    }

    public void printFooterByLicensingOption() {
        printFooterZ()
    }
}

class UltimateLicense {
    public void printHeaderByLicensingOption() {
        printHeaderA();
    }

    public void printFooterByLicensingOption() {
        printFooterA()
    }
}

注意:确保你声明的函数是虚拟的(Java 中的默认值,而不是 C++ 中的默认值)。