好的,下面我们将用状态模式来实现一个模拟从银行卡取钱的流程。
假设我们有以下几个状态:
- 输入卡
- 输入密码
- 选择操作
- 取款
- 取卡
我们通过状态模式来实现这些状态之间的切换。
状态接口
首先,我们定义一个状态接口 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 {@Overridepublic void insertCard(ATMContext context) {System.out.println("Card inserted. Please enter your PIN.");context.setState(new EnterPinState());}@Overridepublic void enterPin(ATMContext context, String pin) {System.out.println("Please insert card first.");}@Overridepublic void selectOperation(ATMContext context, String operation) {System.out.println("Please insert card first.");}@Overridepublic void withdrawCash(ATMContext context, double amount) {System.out.println("Please insert card first.");}@Overridepublic void ejectCard(ATMContext context) {System.out.println("No card to eject.");}
}
EnterPinState.java
public class EnterPinState implements ATMState {@Overridepublic void insertCard(ATMContext context) {System.out.println("Card already inserted. Please enter your PIN.");}@Overridepublic void enterPin(ATMContext context, String pin) {if ("1234".equals(pin)) { // 假设 1234 是正确的 PINSystem.out.println("PIN accepted. Please select operation.");context.setState(new SelectOperationState());} else {System.out.println("Incorrect PIN. Please try again.");}}@Overridepublic void selectOperation(ATMContext context, String operation) {System.out.println("Please enter PIN first.");}@Overridepublic void withdrawCash(ATMContext context, double amount) {System.out.println("Please enter PIN first.");}@Overridepublic void ejectCard(ATMContext context) {System.out.println("Card ejected.");context.setState(new InsertCardState());}
}
SelectOperationState.java
public class SelectOperationState implements ATMState {@Overridepublic void insertCard(ATMContext context) {System.out.println("Card already inserted.");}@Overridepublic void enterPin(ATMContext context, String pin) {System.out.println("PIN already entered.");}@Overridepublic 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.");}}@Overridepublic void withdrawCash(ATMContext context, double amount) {System.out.println("Please select operation first.");}@Overridepublic void ejectCard(ATMContext context) {System.out.println("Card ejected.");context.setState(new InsertCardState());}
}
WithdrawCashState.java
public class WithdrawCashState implements ATMState {@Overridepublic void insertCard(ATMContext context) {System.out.println("Card already inserted.");}@Overridepublic void enterPin(ATMContext context, String pin) {System.out.println("PIN already entered.");}@Overridepublic void selectOperation(ATMContext context, String operation) {System.out.println("Operation already selected.");}@Overridepublic 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.");}}@Overridepublic void ejectCard(ATMContext context) {System.out.println("Please withdraw cash first.");}
}
EjectCardState.java
public class EjectCardState implements ATMState {@Overridepublic void insertCard(ATMContext context) {System.out.println("Please take your card first.");}@Overridepublic void enterPin(ATMContext context, String pin) {System.out.println("Please take your card first.");}@Overridepublic void selectOperation(ATMContext context, String operation) {System.out.println("Please take your card first.");}@Overridepublic void withdrawCash(ATMContext context, double amount) {System.out.println("Please take your card first.");}@Overridepublic 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.
代码说明
-
状态接口:
ATMState
接口定义了在取钱过程中可能出现的各种操作方法。
-
具体状态类:
InsertCardState
、EnterPinState
、SelectOperationState
、WithdrawCashState
和EjectCardState
类分别实现了ATMState
接口,并在每个状态下实现相应的行为和状态转换逻辑。
-
上下文类:
ATMContext
类持有一个ATMState
类型的成员变量state
,用于表示当前状态。ATMContext
的各个方法调用当前状态的相应方法,并根据具体状态类中的实现进行状态转换。
结论
通过使用状态模式,我们将取钱过程中的各个状态和行为封装在独立的状态类中,避免了复杂的条件判断语句,使得代码更加简洁和易于维护。每个状态类只关注自身的行为和状态转换逻辑,这使得系统更具扩展性和可读性。