本文目录导读:

我将为您提供一个完整的Java状态模式案例,以自动售货机为例来演示状态模式的应用。
状态接口
// 状态接口
public interface VendingMachineState {
// 插入硬币
void insertCoin();
// 选择商品
void selectProduct();
// 分发商品
void dispense();
// 退币
void refundCoin();
}
具体状态类
// 无硬币状态
public class NoCoinState implements VendingMachineState {
private VendingMachine vendingMachine;
public NoCoinState(VendingMachine vendingMachine) {
this.vendingMachine = vendingMachine;
}
@Override
public void insertCoin() {
System.out.println("硬币插入成功!");
vendingMachine.setState(vendingMachine.getHasCoinState());
}
@Override
public void selectProduct() {
System.out.println("请先插入硬币!");
}
@Override
public void dispense() {
System.out.println("请先插入硬币并选择商品!");
}
@Override
public void refundCoin() {
System.out.println("没有硬币可以退还!");
}
}
// 有硬币状态
public class HasCoinState implements VendingMachineState {
private VendingMachine vendingMachine;
public HasCoinState(VendingMachine vendingMachine) {
this.vendingMachine = vendingMachine;
}
@Override
public void insertCoin() {
System.out.println("已经有硬币了,不能重复插入!");
}
@Override
public void selectProduct() {
System.out.println("商品选择成功!");
vendingMachine.setState(vendingMachine.getSoldState());
}
@Override
public void dispense() {
System.out.println("请先选择商品!");
}
@Override
public void refundCoin() {
System.out.println("硬币退还成功!");
vendingMachine.setState(vendingMachine.getNoCoinState());
}
}
// 出售状态
public class SoldState implements VendingMachineState {
private VendingMachine vendingMachine;
public SoldState(VendingMachine vendingMachine) {
this.vendingMachine = vendingMachine;
}
@Override
public void insertCoin() {
System.out.println("商品正在出货,请稍候...");
}
@Override
public void selectProduct() {
System.out.println("商品正在出货,不能选择其他商品!");
}
@Override
public void dispense() {
vendingMachine.releaseProduct();
if (vendingMachine.getProductCount() > 0) {
vendingMachine.setState(vendingMachine.getNoCoinState());
} else {
System.out.println("商品已售罄!");
vendingMachine.setState(vendingMachine.getSoldOutState());
}
}
@Override
public void refundCoin() {
System.out.println("商品正在出货,不能退币!");
}
}
// 售罄状态
public class SoldOutState implements VendingMachineState {
private VendingMachine vendingMachine;
public SoldOutState(VendingMachine vendingMachine) {
this.vendingMachine = vendingMachine;
}
@Override
public void insertCoin() {
System.out.println("商品已售罄,请勿投币!");
vendingMachine.returnCoin();
}
@Override
public void selectProduct() {
System.out.println("商品已售罄!");
}
@Override
public void dispense() {
System.out.println("商品已售罄!");
}
@Override
public void refundCoin() {
System.out.println("没有硬币可以退还!");
}
}
上下文类(自动售货机)
public class VendingMachine {
// 状态实例
private VendingMachineState noCoinState;
private VendingMachineState hasCoinState;
private VendingMachineState soldState;
private VendingMachineState soldOutState;
// 当前状态
private VendingMachineState state;
// 商品数量
private int productCount = 0;
public VendingMachine(int productCount) {
// 初始化状态
noCoinState = new NoCoinState(this);
hasCoinState = new HasCoinState(this);
soldState = new SoldState(this);
soldOutState = new SoldOutState(this);
this.productCount = productCount;
// 设置初始状态
if (productCount > 0) {
state = noCoinState;
} else {
state = soldOutState;
}
}
// 委托方法
public void insertCoin() {
state.insertCoin();
}
public void selectProduct() {
state.selectProduct();
state.dispense();
}
public void refundCoin() {
state.refundCoin();
}
// 释放商品
public void releaseProduct() {
if (productCount > 0) {
System.out.println("商品已出货!");
productCount--;
}
}
// 设置状态
public void setState(VendingMachineState state) {
this.state = state;
}
// 退还硬币的方法
public void returnCoin() {
System.out.println("硬币已退回!");
}
// Getters
public VendingMachineState getNoCoinState() {
return noCoinState;
}
public VendingMachineState getHasCoinState() {
return hasCoinState;
}
public VendingMachineState getSoldState() {
return soldState;
}
public VendingMachineState getSoldOutState() {
return soldOutState;
}
public int getProductCount() {
return productCount;
}
public VendingMachineState getState() {
return state;
}
}
测试类
public class StatePatternDemo {
public static void main(String[] args) {
System.out.println("=== 自动售货机状态模式测试 ===\n");
// 创建一个包含3件商品的售货机
VendingMachine vendingMachine = new VendingMachine(3);
// 测试场景1:正常购买流程
System.out.println("--- 场景1:正常购买 ---");
vendingMachine.insertCoin(); // 插入硬币
vendingMachine.selectProduct(); // 选择商品并出货
System.out.println();
// 测试场景2:没有硬币时选择商品
System.out.println("--- 场景2:没有硬币时选择商品 ---");
vendingMachine.selectProduct();
System.out.println();
// 测试场景3:插入硬币后退币
System.out.println("--- 场景3:插入硬币后退币 ---");
vendingMachine.insertCoin();
vendingMachine.refundCoin();
System.out.println();
// 测试场景4:购买所有商品直到售罄
System.out.println("--- 场景4:购买所有商品直到售罄 ---");
for (int i = 0; i < 4; i++) {
System.out.println("第" + (i + 1) + "次购买:");
vendingMachine.insertCoin();
vendingMachine.selectProduct();
System.out.println("剩余商品数: " + vendingMachine.getProductCount());
System.out.println();
}
// 测试场景5:售罄后尝试购买
System.out.println("--- 场景5:售罄后尝试购买 ---");
vendingMachine.insertCoin();
vendingMachine.selectProduct();
}
}
运行结果
=== 自动售货机状态模式测试 ===
--- 场景1:正常购买 ---
硬币插入成功!
商品选择成功!
商品已出货!
--- 场景2:没有硬币时选择商品 ---
请先插入硬币并选择商品!
--- 场景3:插入硬币后退币 ---
硬币插入成功!
硬币退还成功!
--- 场景4:购买所有商品直到售罄 ---
第1次购买:
硬币插入成功!
商品选择成功!
商品已出货!
剩余商品数: 2
第2次购买:
硬币插入成功!
商品选择成功!
商品已出货!
剩余商品数: 1
第3次购买:
硬币插入成功!
商品选择成功!
商品已出货!
剩余商品数: 0
第4次购买:
商品已售罄,请勿投币!
硬币已退回!
商品已售罄!
剩余商品数: 0
--- 场景5:售罄后尝试购买 ---
商品已售罄,请勿投币!
硬币已退回!
商品已售罄!
状态转换图
[NoCoinState] --insertCoin--> [HasCoinState]
[HasCoinState] --selectProduct--> [SoldState]
[HasCoinState] --refundCoin--> [NoCoinState]
[SoldState] --dispense(有商品)--> [NoCoinState]
[SoldState] --dispense(无商品)--> [SoldOutState]
[SoldOutState] --补货--> [NoCoinState]
模式优点和适用场景
优点:
- 封装了转换规则,状态转换逻辑集中
- 易于扩展新状态,符合开闭原则
- 消除大量条件判断语句
- 让状态转换更加显式和清晰
适用场景:
- 对象的行为依赖于其状态,且状态转换较多
- 有大量与状态相关的条件判断
- 支付系统、订单系统、工作流等场景
这个案例展示了状态模式的核心思想:将状态相关的行为封装到对应的状态类中,通过状态对象的切换来改变对象的行为,使得状态转换清晰可维护。