java - 为什么陈述设计模式而不是 If-else

标签 java design-patterns state-pattern

我发现到处都有人说使用状态设计模式比 if else 更好。我想知道为什么:

  1. 它是对现实世界用例中 if-else 的改进吗?
  2. 它是否使代码更易于测试?

任何人都可以提供一个状态模式实际改善情况的例子吗,很难理解为什么我可以使用 if-else 时要承担以下状态模式的开销。

Internet 上的示例不足以说明此模式如何解决现实世界的问题或使代码更易于维护。

最佳答案

我们需要编写代码来解释事实,但让我们先考虑一些问题。状态模式允许您创建流的状态并使用让这些状态决定去哪里和返回什么。好的,假设您不想在每次使用对象和更改其内部值时都控制对象的当前状态。在这种情况下,您的状态可以为您控制自己,并在您调用它时将您发送到正确的位置。 State 模式在处理图形时非常有用,但我将向您展示我在 GoF Design Patterns android 应用程序中看到的另一个示例。

考虑 UML: enter image description here

我们将实现它。

public interface AtmState {
    void withdraw(int amount);
    void refill(int amount);
}

public class Working implements AtmState {

    Atm atm;

    Working(Atm atm) {
        this.atm = atm;
    }

    public void withdraw(int amount) {

        int cashStock = atm.getCashStock();
        if(amount > cashStock) {
            /* Insufficient fund.
            * Dispense the available cash */
            amount = cashStock;
            System.out.print("Partial amount ");
        }

        System.out.println(amount + "$ is dispensed");
        int newCashStock = cashStock - amount;
        atm.setCashStock(newCashStock);
        if(newCashStock == 0) {
            atm.setState(new NoCash(atm));
        }
    }

    public void refill(int amount) {
        System.out.println(amount + "$ is loaded");
        atm.setCashStock(atm.getCashStock()+amount);
    }
}

public class NoCash implements AtmState {

    Atm atm;

    NoCash(Atm atm) {
        this.atm = atm;
    }

    public void withdraw(int amount) {
        System.out.println("Out of cash");
    }

    public void refill(int amount) {
        System.out.println(amount + "$ is loaded");
        atm.setState(new Working(atm));
        atm.setCashStock(atm.getCashStock()+amount);
    }
}

至此我们已经定义了两个相互交互的状态,它们“知道”什么时候从自己变成另一个状态,所以你不需要创建 Controller 来处理什么时候改变对象状态,他们已经知道什么时候该改变了。现在让我们开始我们的 Atm 实现:

public class Atm implements AtmState {
    int cashStock;
    AtmState currentState;

    public Atm() {
        currentState = new NoCash(this);
    }

    public int getCashStock() {
        return cashStock;
    }

    public void setCashStock(int CashStock) {
        this.cashStock = CashStock;
    }

    public void setState(AtmState state) {
        currentState = state;
    }

    public AtmState getState() {
        return currentState;
    }

    public void withdraw(int amount) {
        currentState.withdraw(amount);
    }

    public void refill(int amount) {
        currentState.refill(amount);
    }
}

好的,现在我们有一个对象的两个语句和一个 Atm 实现。现在我们可以单独测试它,这样我们就可以只为 NoCash 状态编写测试,就像我们可以为 Working 状态一样。如您所见,它更加颗粒化。这里有我们的客户端代码:

public class StateClient {

    public static void main(String [] args) {
        Atm atm = new Atm();
        atm.refill(100);
        atm.withdraw(50);
        atm.withdraw(30);
        atm.withdraw(30); // overdraft
        atm.withdraw(20); // overdraft
        atm.refill(50);
        atm.withdraw(50);
    }
}

输出:

100$ is loaded
50$ is dispensed
30$ is dispensed
Partial amount 20$ is dispensed
Out of cash
50$ is loaded
50$ is dispensed

请注意,我们不需要处理 ATM 的状态,我们甚至可以轻松地对其进行测试。除了您没有将 if-else 语句写入您的客户端代码之外,您已经将它写入了状态本身它应该在的位置,因为您的状态需要知道何时检查或不检查它自己而不是你的客户。您的客户只需要得到任何电话的正确答案。

正如我之前所说,测试这个要容易得多,因为现在您可以对任何状态进行单独的小型测试。您的逻辑分布在有意义的地方,您的代码也更容易理解。

希望能帮到你。

关于java - 为什么陈述设计模式而不是 If-else,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55797612/

相关文章:

java - 使用状态模式设计在 Java 中实现通信协议(protocol)

java - 实现状态模式

java - 如何在没有引用的情况下找到类的单例对象?

design-patterns - 对象 C++ 中的状态或观察者模式

java - 在 JAVA 中将 INFINITY 值打印到其他内容

java - 网络服务/面向对象的问题

design-patterns - 如何使用特征对象链实现责任链模式?

design-patterns - 为什么我们需要访问者设计模式中的访问方法?

java - 从包含 java 命令的 java 文件执行 .class

java - 全屏 Swing 框架在 Linux 中无法正确聚焦(Windows 没问题)