Java状态模式案例

wen java案例 3

本文目录导读:

Java状态模式案例

  1. 状态接口
  2. 具体状态类
  3. 上下文类(自动售货机)
  4. 测试类
  5. 运行结果
  6. 状态转换图
  7. 模式优点和适用场景

我将为您提供一个完整的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]

模式优点和适用场景

优点:

  • 封装了转换规则,状态转换逻辑集中
  • 易于扩展新状态,符合开闭原则
  • 消除大量条件判断语句
  • 让状态转换更加显式和清晰

适用场景:

  • 对象的行为依赖于其状态,且状态转换较多
  • 有大量与状态相关的条件判断
  • 支付系统、订单系统、工作流等场景

这个案例展示了状态模式的核心思想:将状态相关的行为封装到对应的状态类中,通过状态对象的切换来改变对象的行为,使得状态转换清晰可维护。

抱歉,评论功能暂时关闭!