以银行卡取钱的流程为例的状态模式的 java 的 demo

好的,下面我们将用状态模式来实现一个模拟从银行卡取钱的流程。

假设我们有以下几个状态:

  1. 输入卡
  2. 输入密码
  3. 选择操作
  4. 取款
  5. 取卡

我们通过状态模式来实现这些状态之间的切换。

状态接口

首先,我们定义一个状态接口 ATMState

// ATMState.java
public interface ATMState {
    void insertCard(ATMContext context);
    void enterPin(ATMContext context, String pin);
    void selectOperation(ATMContext context, String operation);
    void withdrawCash(ATMContext context, double amount);
    void ejectCard(ATMContext context);
}

具体状态类

接下来,我们定义几个具体的状态类,分别实现 ATMState 接口。

InsertCardState.java

public class InsertCardState implements ATMState {
    @Override
    public void insertCard(ATMContext context) {
        System.out.println("Card inserted. Please enter your PIN.");
        context.setState(new EnterPinState());
    }

    @Override
    public void enterPin(ATMContext context, String pin) {
        System.out.println("Please insert card first.");
    }

    @Override
    public void selectOperation(ATMContext context, String operation) {
        System.out.println("Please insert card first.");
    }

    @Override
    public void withdrawCash(ATMContext context, double amount) {
        System.out.println("Please insert card first.");
    }

    @Override
    public void ejectCard(ATMContext context) {
        System.out.println("No card to eject.");
    }
}

EnterPinState.java

public class EnterPinState implements ATMState {
    @Override
    public void insertCard(ATMContext context) {
        System.out.println("Card already inserted. Please enter your PIN.");
    }

    @Override
    public void enterPin(ATMContext context, String pin) {
        if ("1234".equals(pin)) { // 假设 1234 是正确的 PIN
            System.out.println("PIN accepted. Please select operation.");
            context.setState(new SelectOperationState());
        } else {
            System.out.println("Incorrect PIN. Please try again.");
        }
    }

    @Override
    public void selectOperation(ATMContext context, String operation) {
        System.out.println("Please enter PIN first.");
    }

    @Override
    public void withdrawCash(ATMContext context, double amount) {
        System.out.println("Please enter PIN first.");
    }

    @Override
    public void ejectCard(ATMContext context) {
        System.out.println("Card ejected.");
        context.setState(new InsertCardState());
    }
}

SelectOperationState.java

public class SelectOperationState implements ATMState {
    @Override
    public void insertCard(ATMContext context) {
        System.out.println("Card already inserted.");
    }

    @Override
    public void enterPin(ATMContext context, String pin) {
        System.out.println("PIN already entered.");
    }

    @Override
    public void selectOperation(ATMContext context, String operation) {
        if ("withdraw".equalsIgnoreCase(operation)) {
            System.out.println("Operation selected: Withdraw. Please enter amount.");
            context.setState(new WithdrawCashState());
        } else {
            System.out.println("Invalid operation. Please select again.");
        }
    }

    @Override
    public void withdrawCash(ATMContext context, double amount) {
        System.out.println("Please select operation first.");
    }

    @Override
    public void ejectCard(ATMContext context) {
        System.out.println("Card ejected.");
        context.setState(new InsertCardState());
    }
}

WithdrawCashState.java

public class WithdrawCashState implements ATMState {
    @Override
    public void insertCard(ATMContext context) {
        System.out.println("Card already inserted.");
    }

    @Override
    public void enterPin(ATMContext context, String pin) {
        System.out.println("PIN already entered.");
    }

    @Override
    public void selectOperation(ATMContext context, String operation) {
        System.out.println("Operation already selected.");
    }

    @Override
    public void withdrawCash(ATMContext context, double amount) {
        if (amount > 0) {
            System.out.println("Withdrawing " + amount + " dollars. Please take your cash.");
            context.setState(new EjectCardState());
        } else {
            System.out.println("Invalid amount. Please enter again.");
        }
    }

    @Override
    public void ejectCard(ATMContext context) {
        System.out.println("Please withdraw cash first.");
    }
}

EjectCardState.java

public class EjectCardState implements ATMState {
    @Override
    public void insertCard(ATMContext context) {
        System.out.println("Please take your card first.");
    }

    @Override
    public void enterPin(ATMContext context, String pin) {
        System.out.println("Please take your card first.");
    }

    @Override
    public void selectOperation(ATMContext context, String operation) {
        System.out.println("Please take your card first.");
    }

    @Override
    public void withdrawCash(ATMContext context, double amount) {
        System.out.println("Please take your card first.");
    }

    @Override
    public void ejectCard(ATMContext context) {
        System.out.println("Card ejected.");
        context.setState(new InsertCardState());
    }
}

上下文类

最后,我们定义一个上下文类 ATMContext,它持有当前状态并在方法调用时委托给当前状态处理:

// ATMContext.java
public class ATMContext {
    private ATMState state;

    public ATMContext() {
        state = new InsertCardState();
    }

    public void setState(ATMState state) {
        this.state = state;
    }

    public void insertCard() {
        state.insertCard(this);
    }

    public void enterPin(String pin) {
        state.enterPin(this, pin);
    }

    public void selectOperation(String operation) {
        state.selectOperation(this, operation);
    }

    public void withdrawCash(double amount) {
        state.withdrawCash(this, amount);
    }

    public void ejectCard() {
        state.ejectCard(this);
    }

    public static void main(String[] args) {
        ATMContext atm = new ATMContext();

        atm.insertCard();           // 插卡
        atm.enterPin("1234");       // 输入正确的密码
        atm.selectOperation("withdraw"); // 选择取款操作
        atm.withdrawCash(100);      // 取款 100 美元
        atm.ejectCard();            // 弹出卡片
    }
}

运行结果

当我们运行 ATMContext 类中的 main 方法时,会看到以下输出:

Card inserted. Please enter your PIN.
PIN accepted. Please select operation.
Operation selected: Withdraw. Please enter amount.
Withdrawing 100.0 dollars. Please take your cash.
Card ejected.

代码说明

  1. 状态接口

    • ATMState 接口定义了在取钱过程中可能出现的各种操作方法。
  2. 具体状态类

    • InsertCardStateEnterPinStateSelectOperationStateWithdrawCashStateEjectCardState 类分别实现了 ATMState 接口,并在每个状态下实现相应的行为和状态转换逻辑。
  3. 上下文类

    • ATMContext 类持有一个 ATMState 类型的成员变量 state,用于表示当前状态。
    • ATMContext 的各个方法调用当前状态的相应方法,并根据具体状态类中的实现进行状态转换。

结论

通过使用状态模式,我们将取钱过程中的各个状态和行为封装在独立的状态类中,避免了复杂的条件判断语句,使得代码更加简洁和易于维护。每个状态类只关注自身的行为和状态转换逻辑,这使得系统更具扩展性和可读性。

posted @ 2024-07-04 20:13  gongchengship  阅读(6)  评论(0编辑  收藏  举报