以银行卡取钱的流程为例的状态模式的 java 的 demo
好的,下面我们将用状态模式来实现一个模拟从银行卡取钱的流程。
假设我们有以下几个状态:
- 输入卡
- 输入密码
- 选择操作
- 取款
- 取卡
我们通过状态模式来实现这些状态之间的切换。
状态接口
首先,我们定义一个状态接口 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.
代码说明
-
状态接口:
ATMState
接口定义了在取钱过程中可能出现的各种操作方法。
-
具体状态类:
InsertCardState
、EnterPinState
、SelectOperationState
、WithdrawCashState
和EjectCardState
类分别实现了ATMState
接口,并在每个状态下实现相应的行为和状态转换逻辑。
-
上下文类:
ATMContext
类持有一个ATMState
类型的成员变量state
,用于表示当前状态。ATMContext
的各个方法调用当前状态的相应方法,并根据具体状态类中的实现进行状态转换。
结论
通过使用状态模式,我们将取钱过程中的各个状态和行为封装在独立的状态类中,避免了复杂的条件判断语句,使得代码更加简洁和易于维护。每个状态类只关注自身的行为和状态转换逻辑,这使得系统更具扩展性和可读性。