状态模式大白话讲解
一句话概括
就像自动售货机:根据你投入的钱数不同,它会有不同的状态(等待投币→选择商品→出货),每个状态下能做的操作也不同
现实生活比喻
场景1:自动售货机
- 状态1:等待投币 - 显示"请投币",按按钮无效
- 状态2:已投币 - 显示金额,可以按按钮选择商品
- 状态3:出货中 - 正在出货,不能投币也不能按按钮
- 状态4:找零中 - 正在找零,不能进行其他操作
场景2:红绿灯
- 红灯状态:停,不能走
- 绿灯状态:行,可以走
- 黄灯状态:准备,要小心
完整代码示例
场景1:自动售货机
java
/**
* 状态模式 - 自动售货机
*/
public class Main {
public static void main(String[] args) {
System.out.println("=== 自动售货机演示 ===");
// 创建售货机,初始状态为"等待投币"
VendingMachine vendingMachine = new VendingMachine();
// 初始状态
vendingMachine.displayStatus();
System.out.println("\n--- 测试正常购买流程 ---");
// 1. 投币
vendingMachine.insertCoin(5);
// 2. 选择商品
vendingMachine.selectProduct("可乐");
// 3. 出货
vendingMachine.dispenseProduct();
// 4. 找零
vendingMachine.returnChange();
System.out.println("\n--- 测试错误操作 ---");
// 1. 在不该投币的时候投币
System.out.println("\n尝试在错误状态投币:");
vendingMachine.insertCoin(5);
// 2. 重设状态
vendingMachine.reset();
vendingMachine.displayStatus();
System.out.println("\n--- 测试钱不够 ---");
vendingMachine.insertCoin(1); // 可乐需要3元
vendingMachine.selectProduct("可乐");
System.out.println("\n--- 测试多次投币 ---");
vendingMachine.reset();
vendingMachine.insertCoin(2);
vendingMachine.insertCoin(2); // 总共4元
vendingMachine.selectProduct("雪碧");
vendingMachine.dispenseProduct();
vendingMachine.returnChange();
System.out.println("\n--- 测试取消操作 ---");
vendingMachine.reset();
vendingMachine.insertCoin(5);
vendingMachine.cancel();
}
}
/**
* 状态接口
*/
interface VendingMachineState {
void insertCoin(int amount);
void selectProduct(String product);
void dispenseProduct();
void returnChange();
void cancel();
String getStateName();
}
/**
* 具体状态 - 等待投币状态
*/
class WaitingForCoinState implements VendingMachineState {
private VendingMachineContext context;
public WaitingForCoinState(VendingMachineContext context) {
this.context = context;
}
@Override
public void insertCoin(int amount) {
context.addMoney(amount);
System.out.println("投入 " + amount + " 元,当前金额: " + context.getCurrentMoney() + " 元");
if (context.getCurrentMoney() >= 3) { // 假设最低商品价格3元
context.setState(new HasCoinState(context));
System.out.println("状态切换: 等待投币 → 已投币");
}
}
@Override
public void selectProduct(String product) {
System.out.println("❌ 请先投币!");
}
@Override
public void dispenseProduct() {
System.out.println("❌ 请先投币并选择商品!");
}
@Override
public void returnChange() {
System.out.println("❌ 没有投币,无法找零!");
}
@Override
public void cancel() {
System.out.println("❌ 没有投币,无需取消!");
}
@Override
public String getStateName() {
return "等待投币";
}
}
/**
* 具体状态 - 已投币状态
*/
class HasCoinState implements VendingMachineState {
private VendingMachineContext context;
public HasCoinState(VendingMachineContext context) {
this.context = context;
}
@Override
public void insertCoin(int amount) {
context.addMoney(amount);
System.out.println("追加投入 " + amount + " 元,当前金额: " + context.getCurrentMoney() + " 元");
}
@Override
public void selectProduct(String product) {
// 检查商品是否存在
if (!context.hasProduct(product)) {
System.out.println("❌ 商品不存在: " + product);
return;
}
// 检查金额是否足够
int price = context.getProductPrice(product);
if (context.getCurrentMoney() < price) {
System.out.println("❌ 金额不足!" + product + " 需要 " + price + " 元,当前只有 " + context.getCurrentMoney() + " 元");
return;
}
// 设置选择的商品
context.setSelectedProduct(product);
// 计算找零
int change = context.getCurrentMoney() - price;
if (change > 0) {
System.out.println("商品价格: " + price + " 元,需要找零: " + change + " 元");
context.setChange(change);
}
// 切换到出货状态
context.setState(new DispensingState(context));
System.out.println("状态切换: 已投币 → 出货中");
}
@Override
public void dispenseProduct() {
System.out.println("❌ 请先选择商品!");
}
@Override
public void returnChange() {
System.out.println("❌ 请先完成购买!");
}
@Override
public void cancel() {
System.out.println("取消购买,退还 " + context.getCurrentMoney() + " 元");
context.setChange(context.getCurrentMoney());
context.setState(new ReturningChangeState(context));
System.out.println("状态切换: 已投币 → 找零中");
}
@Override
public String getStateName() {
return "已投币";
}
}
/**
* 具体状态 - 出货中状态
*/
class DispensingState implements VendingMachineState {
private VendingMachineContext context;
public DispensingState(VendingMachineContext context) {
this.context = context;
}
@Override
public void insertCoin(int amount) {
System.out.println("❌ 正在出货,请稍后!");
}
@Override
public void selectProduct(String product) {
System.out.println("❌ 正在出货,请稍后!");
}
@Override
public void dispenseProduct() {
String product = context.getSelectedProduct();
System.out.println("正在出货: " + product + "...");
// 模拟出货过程
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("✓ 出货完成: " + product);
// 如果有找零,切换到找零状态,否则回到等待投币状态
if (context.getChange() > 0) {
context.setState(new ReturningChangeState(context));
System.out.println("状态切换: 出货中 → 找零中");
} else {
context.resetTransaction();
context.setState(new WaitingForCoinState(context));
System.out.println("状态切换: 出货中 → 等待投币");
}
}
@Override
public void returnChange() {
System.out.println("❌ 正在出货,请稍后!");
}
@Override
public void cancel() {
System.out.println("❌ 正在出货,无法取消!");
}
@Override
public String getStateName() {
return "出货中";
}
}
/**
* 具体状态 - 找零中状态
*/
class ReturningChangeState implements VendingMachineState {
private VendingMachineContext context;
public ReturningChangeState(VendingMachineContext context) {
this.context = context;
}
@Override
public void insertCoin(int amount) {
System.out.println("❌ 正在找零,请稍后!");
}
@Override
public void selectProduct(String product) {
System.out.println("❌ 正在找零,请稍后!");
}
@Override
public void dispenseProduct() {
System.out.println("❌ 正在找零,请稍后!");
}
@Override
public void returnChange() {
int change = context.getChange();
if (change > 0) {
System.out.println("正在找零 " + change + " 元...");
// 模拟找零过程
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("✓ 找零完成: " + change + " 元");
} else {
System.out.println("无需找零");
}
// 重置交易,回到等待投币状态
context.resetTransaction();
context.setState(new WaitingForCoinState(context));
System.out.println("状态切换: 找零中 → 等待投币");
}
@Override
public void cancel() {
System.out.println("❌ 正在找零,无法取消!");
}
@Override
public String getStateName() {
return "找零中";
}
}
/**
* 上下文类 - 自动售货机
*/
class VendingMachineContext {
private VendingMachineState state;
private int currentMoney;
private String selectedProduct;
private int change;
// 商品库存和价格
private Map<String, Integer> products = new HashMap<>();
public VendingMachineContext() {
// 初始化商品
products.put("可乐", 3);
products.put("雪碧", 3);
products.put("矿泉水", 2);
products.put("咖啡", 5);
products.put("红茶", 4);
// 初始状态为等待投币
this.state = new WaitingForCoinState(this);
this.currentMoney = 0;
}
// 设置状态
public void setState(VendingMachineState state) {
this.state = state;
}
// 获取当前状态
public VendingMachineState getState() {
return state;
}
// 操作方法 - 委托给当前状态
public void insertCoin(int amount) {
state.insertCoin(amount);
}
public void selectProduct(String product) {
state.selectProduct(product);
}
public void dispenseProduct() {
state.dispenseProduct();
}
public void returnChange() {
state.returnChange();
}
public void cancel() {
state.cancel();
}
// 其他方法
public void addMoney(int amount) {
this.currentMoney += amount;
}
public int getCurrentMoney() {
return currentMoney;
}
public boolean hasProduct(String product) {
return products.containsKey(product);
}
public int getProductPrice(String product) {
return products.getOrDefault(product, 0);
}
public void setSelectedProduct(String product) {
this.selectedProduct = product;
}
public String getSelectedProduct() {
return selectedProduct;
}
public void setChange(int change) {
this.change = change;
}
public int getChange() {
return change;
}
// 重置交易
public void resetTransaction() {
this.currentMoney = 0;
this.selectedProduct = null;
this.change = 0;
}
// 重置售货机
public void reset() {
resetTransaction();
this.state = new WaitingForCoinState(this);
System.out.println("售货机已重置");
}
// 显示状态
public void displayStatus() {
System.out.println("当前状态: " + state.getStateName());
System.out.println("当前金额: " + currentMoney + " 元");
System.out.println("已选商品: " + (selectedProduct != null ? selectedProduct : "无"));
System.out.println("需要找零: " + change + " 元");
}
}
/**
* 客户端类 - 包装售货机
*/
class VendingMachine {
private VendingMachineContext context;
public VendingMachine() {
this.context = new VendingMachineContext();
}
// 操作方法
public void insertCoin(int amount) {
System.out.println("\n[操作] 投币 " + amount + " 元");
context.insertCoin(amount);
}
public void selectProduct(String product) {
System.out.println("\n[操作] 选择商品: " + product);
context.selectProduct(product);
}
public void dispenseProduct() {
System.out.println("\n[操作] 出货");
context.dispenseProduct();
}
public void returnChange() {
System.out.println("\n[操作] 找零");
context.returnChange();
}
public void cancel() {
System.out.println("\n[操作] 取消");
context.cancel();
}
public void reset() {
System.out.println("\n[操作] 重置");
context.reset();
}
public void displayStatus() {
System.out.println("\n=== 售货机状态 ===");
context.displayStatus();
}
}
运行结果
=== 自动售货机演示 ===
=== 售货机状态 ===
当前状态: 等待投币
当前金额: 0 元
已选商品: 无
需要找零: 0 元
--- 测试正常购买流程 ---
[操作] 投币 5 元
投入 5 元,当前金额: 5 元
状态切换: 等待投币 → 已投币
[操作] 选择商品: 可乐
商品价格: 3 元,需要找零: 2 元
状态切换: 已投币 → 出货中
[操作] 出货
正在出货: 可乐...
✓ 出货完成: 可乐
状态切换: 出货中 → 找零中
[操作] 找零
正在找零 2 元...
✓ 找零完成: 2 元
状态切换: 找零中 → 等待投币
--- 测试错误操作 ---
尝试在错误状态投币:
[操作] 投币 5 元
❌ 请先投币!
[操作] 重置
售货机已重置
=== 售货机状态 ===
当前状态: 等待投币
当前金额: 0 元
已选商品: 无
需要找零: 0 元
--- 测试钱不够 ---
[操作] 投币 1 元
投入 1 元,当前金额: 1 元
[操作] 选择商品: 可乐
❌ 金额不足!可乐 需要 3 元,当前只有 1 元
--- 测试多次投币 ---
[操作] 重置
售货机已重置
[操作] 投币 2 元
投入 2 元,当前金额: 2 元
[操作] 投币 2 元
追加投入 2 元,当前金额: 4 元
[操作] 选择商品: 雪碧
商品价格: 3 元,需要找零: 1 元
状态切换: 已投币 → 出货中
[操作] 出货
正在出货: 雪碧...
✓ 出货完成: 雪碧
状态切换: 出货中 → 找零中
[操作] 找零
正在找零 1 元...
✓ 找零完成: 1 元
状态切换: 找零中 → 等待投币
--- 测试取消操作 ---
[操作] 重置
售货机已重置
[操作] 投币 5 元
投入 5 元,当前金额: 5 元
状态切换: 等待投币 → 已投币
[操作] 取消
取消购买,退还 5 元
状态切换: 已投币 → 找零中

场景2:订单状态流转(企业级示例)
java
/**
* 状态模式 - 订单状态管理
*/
public class OrderStateExample {
public static void main(String[] args) {
System.out.println("=== 订单状态管理系统 ===");
// 创建订单
Order order = new Order("ORD001", "张三", 100.0);
// 显示初始状态
order.display();
System.out.println("\n=== 正常订单流程 ===");
// 1. 付款
System.out.println("\n--- 步骤1: 付款 ---");
order.pay();
order.display();
// 2. 发货
System.out.println("\n--- 步骤2: 发货 ---");
order.ship();
order.display();
// 3. 确认收货
System.out.println("\n--- 步骤3: 确认收货 ---");
order.confirm();
order.display();
// 4. 完成
System.out.println("\n--- 步骤4: 完成 ---");
order.complete();
order.display();
System.out.println("\n=== 测试取消订单 ===");
// 创建新订单
Order order2 = new Order("ORD002", "李四", 200.0);
order2.display();
// 付款
System.out.println("\n--- 付款 ---");
order2.pay();
order2.display();
// 取消订单(在已付款状态)
System.out.println("\n--- 取消订单 ---");
order2.cancel();
order2.display();
// 尝试在取消状态继续操作
System.out.println("\n--- 尝试在取消状态发货 ---");
order2.ship();
System.out.println("\n=== 测试退货流程 ===");
// 创建新订单
Order order3 = new Order("ORD003", "王五", 150.0);
order3.display();
// 完整购买流程
System.out.println("\n--- 完整购买流程 ---");
order3.pay();
order3.ship();
order3.confirm();
order3.display();
// 申请退货
System.out.println("\n--- 申请退货 ---");
order3.requestReturn();
order3.display();
// 处理退货
System.out.println("\n--- 处理退货 ---");
order3.processReturn();
order3.display();
// 完成退货
System.out.println("\n--- 完成退货 ---");
order3.completeReturn();
order3.display();
System.out.println("\n=== 测试错误操作 ===");
// 创建新订单
Order order4 = new Order("ORD004", "赵六", 80.0);
// 尝试在未付款状态发货
System.out.println("\n--- 尝试在未付款状态发货 ---");
order4.ship();
// 尝试在未发货状态确认收货
System.out.println("\n--- 尝试在未发货状态确认收货 ---");
order4.confirm();
// 显示所有订单状态
System.out.println("\n=== 所有订单状态 ===");
System.out.println("订单1: " + order.getStatus());
System.out.println("订单2: " + order2.getStatus());
System.out.println("订单3: " + order3.getStatus());
System.out.println("订单4: " + order4.getStatus());
}
}
/**
* 订单状态接口
*/
interface OrderState {
void pay(OrderContext context);
void ship(OrderContext context);
void confirm(OrderContext context);
void complete(OrderContext context);
void cancel(OrderContext context);
void requestReturn(OrderContext context);
void processReturn(OrderContext context);
void completeReturn(OrderContext context);
String getStateName();
}
/**
* 具体状态 - 待付款
*/
class PendingPaymentState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("✓ 付款成功");
context.setState(new PaidState());
context.log("状态: 待付款 → 已付款");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单未付款");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单未发货");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单未确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("✓ 订单已取消");
context.setState(new CancelledState());
context.log("状态: 待付款 → 已取消");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法申请退货:订单未完成");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:没有退货申请");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:没有退货申请");
}
@Override
public String getStateName() {
return "待付款";
}
}
/**
* 具体状态 - 已付款
*/
class PaidState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法重复付款:订单已付款");
}
@Override
public void ship(OrderContext context) {
System.out.println("✓ 订单已发货");
context.setState(new ShippedState());
context.log("状态: 已付款 → 已发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单未发货");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单未确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("✓ 订单已取消,退款处理中...");
context.setState(new CancelledState());
context.log("状态: 已付款 → 已取消(需退款)");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法申请退货:订单未完成");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:没有退货申请");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:没有退货申请");
}
@Override
public String getStateName() {
return "已付款";
}
}
/**
* 具体状态 - 已发货
*/
class ShippedState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单已付款");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法重复发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("✓ 订单已确认收货");
context.setState(new ConfirmedState());
context.log("状态: 已发货 → 已确认收货");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:需要先确认收货");
}
@Override
public void cancel(OrderContext context) {
System.out.println("⚠️ 订单已发货,请联系客服处理取消");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法申请退货:订单未完成");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:没有退货申请");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:没有退货申请");
}
@Override
public String getStateName() {
return "已发货";
}
}
/**
* 具体状态 - 已确认收货
*/
class ConfirmedState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单已完成付款");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单已发货");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法重复确认收货");
}
@Override
public void complete(OrderContext context) {
System.out.println("✓ 订单已完成");
context.setState(new CompletedState());
context.log("状态: 已确认收货 → 已完成");
}
@Override
public void cancel(OrderContext context) {
System.out.println("❌ 无法取消:订单已确认收货");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("✓ 退货申请已提交");
context.setState(new ReturnRequestedState());
context.log("状态: 已确认收货 → 退货申请中");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:需要先申请退货");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:需要先申请退货");
}
@Override
public String getStateName() {
return "已确认收货";
}
}
/**
* 具体状态 - 已完成
*/
class CompletedState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单已完成");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单已完成");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单已完成");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法重复完成订单");
}
@Override
public void cancel(OrderContext context) {
System.out.println("❌ 无法取消:订单已完成");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("✓ 退货申请已提交");
context.setState(new ReturnRequestedState());
context.log("状态: 已完成 → 退货申请中");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:需要先申请退货");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:需要先申请退货");
}
@Override
public String getStateName() {
return "已完成";
}
}
/**
* 具体状态 - 已取消
*/
class CancelledState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单已取消");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单已取消");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单已取消");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单已取消");
}
@Override
public void cancel(OrderContext context) {
System.out.println("❌ 无法重复取消");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法申请退货:订单已取消");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:订单已取消");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:订单已取消");
}
@Override
public String getStateName() {
return "已取消";
}
}
/**
* 具体状态 - 退货申请中
*/
class ReturnRequestedState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单有退货申请");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单有退货申请");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单有退货申请");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单有退货申请");
}
@Override
public void cancel(OrderContext context) {
System.out.println("⚠️ 订单有退货申请,请联系客服处理");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法重复申请退货");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("✓ 退货申请已通过,请寄回商品");
context.setState(new ReturnProcessingState());
context.log("状态: 退货申请中 → 退货处理中");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法完成退货:需要先处理退货申请");
}
@Override
public String getStateName() {
return "退货申请中";
}
}
/**
* 具体状态 - 退货处理中
*/
class ReturnProcessingState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单在退货中");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单在退货中");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单在退货中");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单在退货中");
}
@Override
public void cancel(OrderContext context) {
System.out.println("⚠️ 订单在退货中,请联系客服处理");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法重复申请退货");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法重复处理退货");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("✓ 退货已完成,退款已处理");
context.setState(new ReturnCompletedState());
context.log("状态: 退货处理中 → 退货已完成");
}
@Override
public String getStateName() {
return "退货处理中";
}
}
/**
* 具体状态 - 退货已完成
*/
class ReturnCompletedState implements OrderState {
@Override
public void pay(OrderContext context) {
System.out.println("❌ 无法付款:订单已退货完成");
}
@Override
public void ship(OrderContext context) {
System.out.println("❌ 无法发货:订单已退货完成");
}
@Override
public void confirm(OrderContext context) {
System.out.println("❌ 无法确认收货:订单已退货完成");
}
@Override
public void complete(OrderContext context) {
System.out.println("❌ 无法完成订单:订单已退货完成");
}
@Override
public void cancel(OrderContext context) {
System.out.println("❌ 无法取消:订单已退货完成");
}
@Override
public void requestReturn(OrderContext context) {
System.out.println("❌ 无法申请退货:订单已退货完成");
}
@Override
public void processReturn(OrderContext context) {
System.out.println("❌ 无法处理退货:订单已退货完成");
}
@Override
public void completeReturn(OrderContext context) {
System.out.println("❌ 无法重复完成退货");
}
@Override
public String getStateName() {
return "退货已完成";
}
}
/**
* 订单上下文
*/
class OrderContext {
private OrderState state;
private List<String> history = new ArrayList<>();
public OrderContext() {
this.state = new PendingPaymentState();
log("订单创建,初始状态: 待付款");
}
public void setState(OrderState state) {
this.state = state;
}
public OrderState getState() {
return state;
}
public void log(String message) {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
history.add(sdf.format(new Date()) + " - " + message);
}
public List<String> getHistory() {
return new ArrayList<>(history);
}
public String getStatus() {
return state.getStateName();
}
}
/**
* 订单类
*/
class Order {
private String orderId;
private String customerName;
private double amount;
private OrderContext context;
public Order(String orderId, String customerName, double amount) {
this.orderId = orderId;
this.customerName = customerName;
this.amount = amount;
this.context = new OrderContext();
}
// 操作方法
public void pay() {
System.out.println("操作: 付款");
context.pay(context);
}
public void ship() {
System.out.println("操作: 发货");
context.ship(context);
}
public void confirm() {
System.out.println("操作: 确认收货");
context.confirm(context);
}
public void complete() {
System.out.println("操作: 完成订单");
context.complete(context);
}
public void cancel() {
System.out.println("操作: 取消订单");
context.cancel(context);
}
public void requestReturn() {
System.out.println("操作: 申请退货");
context.requestReturn(context);
}
public void processReturn() {
System.out.println("操作: 处理退货");
context.processReturn(context);
}
public void completeReturn() {
System.out.println("操作: 完成退货");
context.completeReturn(context);
}
public String getStatus() {
return context.getStatus();
}
public void display() {
System.out.println("\n=== 订单信息 ===");
System.out.println("订单号: " + orderId);
System.out.println("客户: " + customerName);
System.out.println("金额: ¥" + amount);
System.out.println("状态: " + getStatus());
System.out.println("\n状态历史:");
List<String> history = context.getHistory();
if (history.isEmpty()) {
System.out.println(" 无");
} else {
for (String record : history) {
System.out.println(" " + record);
}
}
}
}
运行结果
=== 订单状态管理系统 ===
=== 订单信息 ===
订单号: ORD001
客户: 张三
金额: ¥100.0
状态: 待付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
=== 正常订单流程 ===
--- 步骤1: 付款 ---
操作: 付款
✓ 付款成功
状态: 待付款 → 已付款
=== 订单信息 ===
订单号: ORD001
客户: 张三
金额: ¥100.0
状态: 已付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
--- 步骤2: 发货 ---
操作: 发货
✓ 订单已发货
状态: 已付款 → 已发货
=== 订单信息 ===
订单号: ORD001
客户: 张三
金额: ¥100.0
状态: 已发货
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
--- 步骤3: 确认收货 ---
操作: 确认收货
✓ 订单已确认收货
状态: 已发货 → 已确认收货
=== 订单信息 ===
订单号: ORD001
客户: 张三
金额: ¥100.0
状态: 已确认收货
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
--- 步骤4: 完成 ---
操作: 完成订单
✓ 订单已完成
状态: 已确认收货 → 已完成
=== 订单信息 ===
订单号: ORD001
客户: 张三
金额: ¥100.0
状态: 已完成
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
14:50:22 - 状态: 已确认收货 → 已完成
=== 测试取消订单 ===
=== 订单信息 ===
订单号: ORD002
客户: 李四
金额: ¥200.0
状态: 待付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
--- 付款 ---
操作: 付款
✓ 付款成功
状态: 待付款 → 已付款
=== 订单信息 ===
订单号: ORD002
客户: 李四
金额: ¥200.0
状态: 已付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
--- 取消订单 ---
操作: 取消订单
✓ 订单已取消,退款处理中...
状态: 已付款 → 已取消(需退款)
=== 订单信息 ===
订单号: ORD002
客户: 李四
金额: ¥200.0
状态: 已取消
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已取消(需退款)
--- 尝试在取消状态发货 ---
操作: 发货
❌ 无法发货:订单已取消
=== 测试退货流程 ===
=== 订单信息 ===
订单号: ORD003
客户: 王五
金额: ¥150.0
状态: 待付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
--- 完整购买流程 ---
操作: 付款
✓ 付款成功
状态: 待付款 → 已付款
操作: 发货
✓ 订单已发货
状态: 已付款 → 已发货
操作: 确认收货
✓ 订单已确认收货
状态: 已发货 → 已确认收货
=== 订单信息 ===
订单号: ORD003
客户: 王五
金额: ¥150.0
状态: 已确认收货
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
--- 申请退货 ---
操作: 申请退货
✓ 退货申请已提交
状态: 已确认收货 → 退货申请中
=== 订单信息 ===
订单号: ORD003
客户: 王五
金额: ¥150.0
状态: 退货申请中
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
14:50:22 - 状态: 已确认收货 → 退货申请中
--- 处理退货 ---
操作: 处理退货
✓ 退货申请已通过,请寄回商品
状态: 退货申请中 → 退货处理中
=== 订单信息 ===
订单号: ORD003
客户: 王五
金额: ¥150.0
状态: 退货处理中
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
14:50:22 - 状态: 已确认收货 → 退货申请中
14:50:22 - 状态: 退货申请中 → 退货处理中
--- 完成退货 ---
操作: 完成退货
✓ 退货已完成,退款已处理
状态: 退货处理中 → 退货已完成
=== 订单信息 ===
订单号: ORD003
客户: 王五
金额: ¥150.0
状态: 退货已完成
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
14:50:22 - 状态: 待付款 → 已付款
14:50:22 - 状态: 已付款 → 已发货
14:50:22 - 状态: 已发货 → 已确认收货
14:50:22 - 状态: 已确认收货 → 退货申请中
14:50:22 - 状态: 退货申请中 → 退货处理中
14:50:22 - 状态: 退货处理中 → 退货已完成
=== 测试错误操作 ===
=== 订单信息 ===
订单号: ORD004
客户: 赵六
金额: ¥80.0
状态: 待付款
状态历史:
14:50:22 - 订单创建,初始状态: 待付款
--- 尝试在未付款状态发货 ---
操作: 发货
❌ 无法发货:订单未付款
--- 尝试在未发货状态确认收货 ---
操作: 确认收货
❌ 无法确认收货:订单未发货
=== 所有订单状态 ===
订单1: 已完成
订单2: 已取消
订单3: 退货已完成
订单4: 待付款
状态模式的核心结构
Context(上下文)
↑
| 维护
|
State(状态接口)
↑
ConcreteState(具体状态) → 每个状态知道下一个状态
关键特征:
- 状态封装:每个状态的行为封装在单独的类中
- 状态切换:上下文根据条件切换到不同状态
- 消除条件判断:避免了大量的if-else或switch-case
- 符合开闭原则:新增状态不影响现有代码
状态模式 vs 策略模式
| 特性 | 状态模式 | 策略模式 |
|---|---|---|
| 目的 | 处理对象的状态变化 | 封装可互换的算法 |
| 状态切换 | 状态间知道彼此,自动切换 | 策略间不知道彼此,客户端选择 |
| 关注点 | 对象内部状态的变化 | 算法的选择和替换 |
| 典型应用 | 订单状态、游戏角色状态 | 排序算法、支付策略 |
适用场景(大白话版)
✅ 适合用状态模式的场景:
-
对象有多个状态
java// 订单状态:待付款→已付款→已发货→已完成 // 游戏角色状态:正常→中毒→眩晕→死亡 -
状态影响行为
java// 不同状态下,相同操作有不同行为 // 比如:红灯停,绿灯行 -
状态转换复杂
java// 状态转换有很多条件判断 // 使用状态模式可以消除大量if-else -
需要状态历史
java// 需要记录状态变化历史 // 支持撤销/重做状态
❌ 不适合的场景:
- 状态很少或简单:只有2-3个状态且不会变化
- 状态不改变行为:状态变化不影响对象行为
- 性能敏感:状态切换有开销
- 状态数量固定:状态不会再增加
优缺点
优点:
- 消除条件判断:用多态代替if-else
- 单一职责:每个状态类只负责一个状态
- 开闭原则:容易增加新状态
- 状态转换明确:状态转换逻辑清晰
缺点:
- 增加类的数量:每个状态一个类
- 可能过度设计:简单状态机可能不需要
- 状态切换开销:频繁切换可能影响性能
- 可能循环依赖:状态类之间可能相互引用
实际应用案例
1. TCP连接状态
java
// TCP连接的状态:CLOSED, LISTEN, SYN_SENT, ESTABLISHED等
class TCPConnection {
private TCPState state;
public void open() { state.open(); }
public void close() { state.close(); }
public void acknowledge() { state.acknowledge(); }
}
2. 游戏角色状态
java
// 游戏角色状态:站立、行走、奔跑、跳跃、攻击等
class GameCharacter {
private CharacterState state;
public void move() { state.move(); }
public void jump() { state.jump(); }
public void attack() { state.attack(); }
}
3. 工作流引擎
java
// 工作流状态:草稿、审批中、已批准、已拒绝、已完成
class Workflow {
private WorkflowState state;
public void submit() { state.submit(); }
public void approve() { state.approve(); }
public void reject() { state.reject(); }
}
4. 交通信号灯
java
// 红绿灯状态:红、黄、绿
class TrafficLight {
private LightState state;
public void change() { state.change(); } // 自动切换到下一个状态
public void stop() { state.stop(); }
public void go() { state.go(); }
}
实现技巧
1. 状态表驱动
java
// 使用表驱动定义状态转换
Map<State, Map<Event, State>> transitionTable = new HashMap<>();
transitionTable.put(State.A, Map.of(Event.X, State.B, Event.Y, State.C));
2. 状态工厂
java
// 使用工厂创建状态对象
class StateFactory {
public static State createState(String type) {
switch (type) {
case "A": return new StateA();
case "B": return new StateB();
default: throw new IllegalArgumentException();
}
}
}
3. 状态上下文传递
java
// 状态可以通过上下文访问共享数据
interface State {
void doAction(Context context);
}
4. 状态历史记录
java
// 记录状态历史,支持撤销
class StateHistory {
private Stack<State> history = new Stack<>();
public void push(State state) { history.push(state); }
public State pop() { return history.pop(); }
}
总结
状态模式就是:
- 红绿灯:红灯停、绿灯行、黄灯等,每个状态行为不同
- 游戏角色:站立能走、跳跃中不能攻击、死亡啥都不能做
- 自动售货机:没投币不能选商品,选了商品才能出货
- 订单状态:待付款只能付款,已发货才能确认收货
核心口诀:
对象状态常变化,
行为跟着状态走。
消除if-else判断,
状态类里封逻辑!
就像现实中的:
- 🚦 交通信号灯:红黄绿,不同颜色不同规则
- 🎮 游戏机:开机、待机、运行、关机,不同状态不同操作
- 🏦 ATM机:插卡→输入密码→选择服务→取款→退卡,一步步来
- 🏥 病人状态:挂号→就诊→检查→取药→离院,流程清晰
记住:当一个对象的行为取决于它的状态,并且它需要在运行时根据状态改变行为时,考虑使用状态模式!