Deepeek用大白话讲解 --> 状态模式(企业级场景1,自动售货机2,订单状态3,消除if-else4)

状态模式大白话讲解

一句话概括

就像自动售货机:根据你投入的钱数不同,它会有不同的状态(等待投币→选择商品→出货),每个状态下能做的操作也不同


现实生活比喻

场景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 策略模式

特性 状态模式 策略模式
目的 处理对象的状态变化 封装可互换的算法
状态切换 状态间知道彼此,自动切换 策略间不知道彼此,客户端选择
关注点 对象内部状态的变化 算法的选择和替换
典型应用 订单状态、游戏角色状态 排序算法、支付策略

适用场景(大白话版)

适合用状态模式的场景:

  1. 对象有多个状态

    java 复制代码
    // 订单状态:待付款→已付款→已发货→已完成
    // 游戏角色状态:正常→中毒→眩晕→死亡
  2. 状态影响行为

    java 复制代码
    // 不同状态下,相同操作有不同行为
    // 比如:红灯停,绿灯行
  3. 状态转换复杂

    java 复制代码
    // 状态转换有很多条件判断
    // 使用状态模式可以消除大量if-else
  4. 需要状态历史

    java 复制代码
    // 需要记录状态变化历史
    // 支持撤销/重做状态

不适合的场景:

  1. 状态很少或简单:只有2-3个状态且不会变化
  2. 状态不改变行为:状态变化不影响对象行为
  3. 性能敏感:状态切换有开销
  4. 状态数量固定:状态不会再增加

优缺点

优点:

  • 消除条件判断:用多态代替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机:插卡→输入密码→选择服务→取款→退卡,一步步来
  • 🏥 病人状态:挂号→就诊→检查→取药→离院,流程清晰

记住:当一个对象的行为取决于它的状态,并且它需要在运行时根据状态改变行为时,考虑使用状态模式!

相关推荐
掉鱼的猫2 小时前
超越 SpringBoot 4.0了吗?OpenSolon v3.8, v3.7.4, v3.6.7 发布
java·spring boot
廋到被风吹走2 小时前
【Spring】InitializingBean 深度解析:Spring Bean 的“初始化回调接口“
java·后端·spring
yzp-2 小时前
记录一个死锁异常--循环打印 AB go语言
开发语言·后端·golang
andwhataboutit?2 小时前
LANGGRAPH
java·服务器·前端
毕设源码-邱学长2 小时前
【开题答辩全过程】以 基于springboot的社区团购小程序设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
风月歌2 小时前
小程序项目之超市售货管理平台小程序源代码(源码+文档)
java·微信小程序·小程序·毕业设计·源码
SimonKing2 小时前
浅谈银行系统对接中的安全和槽点
java·后端·程序员
tryxr2 小时前
Java 中 this 关键字的使用场景
java·开发语言·类与对象·this关键字
Coder_Boy_2 小时前
Spring 核心思想与企业级最佳特性(思想级)
java·后端·spring