文章目录
- [1. 生活中的例子](#1. 生活中的例子)
-
- [1.1 自动售货机 🎮](#1.1 自动售货机 🎮)
- [1.2 汽车档位 🚗](#1.2 汽车档位 🚗)
- [1.3 核心思想提炼 💡](#1.3 核心思想提炼 💡)
- [2. 代码中的例子](#2. 代码中的例子)
-
- [2.1 基础结构📦](#2.1 基础结构📦)
- [2.2 自动售货机 🛒](#2.2 自动售货机 🛒)
- [2.2 交通信号灯 🚦](#2.2 交通信号灯 🚦)
- [3. 归纳总结](#3. 归纳总结)
-
- [3.1 状态模式核心总结 📊](#3.1 状态模式核心总结 📊)
- [3.2 ✅ 状态模式的优点](#3.2 ✅ 状态模式的优点)
- [3.3 使用时机⚠️](#3.3 使用时机⚠️)
- [3.4 状态模式 vs 策略模式🔄](#3.4 状态模式 vs 策略模式🔄)
- [4. 补充知识💡](#4. 补充知识💡)
-
- [4.1 状态管理的方式](#4.1 状态管理的方式)
- [4.2 状态共享](#4.2 状态共享)
1. 生活中的例子
1.1 自动售货机 🎮
场景: 想象一台自动售货机,它有几种状态:
- 待机状态:等待投币
- 已投币状态:已经投入了钱
- 出货状态:正在出货
- 缺货状态:商品卖完了
生动比喻: 售货机就像一个会变身的机器人
- 当它是"待机机器人"时,只会说:"请投币"
- 当变成"已投币机器人"时,会说:"请选择商品"
- 当变成"出货机器人"时,会说:"正在出货,请稍等"
- 当变成"缺货机器人"时,会说:"商品已售罄"
关键点: 同一个售货机,在不同状态下,对同一个按钮(比如"按按钮")的反应完全不同!
1.2 汽车档位 🚗
场景: 汽车有P(停车)、R(倒车)、N(空档)、D(行驶)等档位
生动比喻: 汽车变速箱就是一个状态机
- P档状态:踩油门 → 车子不动(保护状态)
- R档状态:踩油门 → 车子倒退
- D档状态:踩油门 → 车子前进
- N档状态:踩油门 → 发动机空转,车子不动
讲解: 同样的"踩油门"动作,在不同档位状态下产生完全不同的结果!这就是状态模式的核心思思。
1.3 核心思想提炼 💡
就像一个人在不同情绪状态下,对同一句话的反应不同:
- 开心时听到批评 → 一笑而过
- 生气时听到批评 → 大发雷霆
- 悲伤时听到批评 → 更加难过
状态模式就是:让对象在不同状态下改变它的行为,就像变了一个人一样!
2. 代码中的例子
2.1 基础结构📦
状态模式三要素
java
// 1. 状态接口(定义所有状态共有的行为)
interface State {
void handle(Context context);
}
// 2. 具体状态类(实现不同状态下的行为)
class ConcreteStateA implements State {
@Override
public void handle(Context context) {
System.out.println("当前是状态A,执行A的行为");
context.setState(new ConcreteStateB()); // 切换到下一个状态
}
}
class ConcreteStateB implements State {
@Override
public void handle(Context context) {
System.out.println("当前是状态B,执行B的行为");
context.setState(new ConcreteStateA()); // 切换回状态A
}
}
// 3. 上下文类(持有状态引用)
class Context {
private State state;
public Context(State state) {
this.state = state;
}
public void setState(State state) {
this.state = state;
}
public void request() {
state.handle(this); // 委托给当前状态处理
}
}
2.2 自动售货机 🛒
java
import java.util.HashMap;
import java.util.Map;
// 状态接口
interface VendingMachineState {
void insertCoin(VendingMachine machine);
void pressButton(VendingMachine machine);
void dispense(VendingMachine machine);
}
// 具体状态类
class IdleState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine machine) {
System.out.println("✅ 硬币已投入");
machine.setState(new HasCoinState());
}
@Override
public void pressButton(VendingMachine machine) {
System.out.println("❌ 请先投入硬币");
}
@Override
public void dispense(VendingMachine machine) {
System.out.println("❌ 请先投入硬币并选择商品");
}
}
class HasCoinState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine machine) {
System.out.println("❌ 已投入硬币,请先选择商品");
}
@Override
public void pressButton(VendingMachine machine) {
if (machine.getStock() > 0) {
System.out.println("✅ 商品选择成功,准备出货");
machine.setState(new DispensingState());
} else {
System.out.println("❌ 商品已售罄,退回硬币");
machine.setState(new IdleState());
}
}
@Override
public void dispense(VendingMachine machine) {
System.out.println("❌ 请先选择商品");
}
}
class DispensingState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine machine) {
System.out.println("❌ 正在出货,请稍候");
}
@Override
public void pressButton(VendingMachine machine) {
System.out.println("❌ 正在出货,请稍候");
}
@Override
public void dispense(VendingMachine machine) {
machine.releaseProduct();
System.out.println("✅ 商品已出货,感谢购买");
machine.reduceStock();
machine.setState(machine.getStock() > 0 ? new IdleState() : new SoldOutState());
}
}
class SoldOutState implements VendingMachineState {
@Override
public void insertCoin(VendingMachine machine) {
System.out.println("❌ 商品已售罄,无法投币");
}
@Override
public void pressButton(VendingMachine machine) {
System.out.println("❌ 商品已售罄");
}
@Override
public void dispense(VendingMachine machine) {
System.out.println("❌ 商品已售罄");
}
}
// 上下文类 - 自动售货机
class VendingMachine {
private VendingMachineState state;
private int stock;
private Map<String, Integer> products;
public VendingMachine(int stock) {
this.stock = stock;
this.state = new IdleState();
this.products = new HashMap<>();
products.put("可乐", 3);
products.put("薯片", 5);
}
public void setState(VendingMachineState state) {
this.state = state;
}
public int getStock() {
return stock;
}
public void reduceStock() {
if (stock > 0) stock--;
}
public void releaseProduct() {
System.out.println("机器发出商品...");
}
// 用户操作
public void insertCoin() {
state.insertCoin(this);
}
public void pressButton() {
state.pressButton(this);
}
public void dispense() {
state.dispense(this);
}
}
// 测试代码
public class StatePatternDemo {
public static void main(String[] args) {
System.out.println("=== 自动售货机状态模式演示 ===\n");
VendingMachine machine = new VendingMachine(2);
// 场景1:正常购买流程
System.out.println("【场景1:正常购买】");
machine.insertCoin(); // 投币
machine.pressButton(); // 选择商品
machine.dispense(); // 出货
System.out.println("\n【场景2:再次购买】");
machine.insertCoin();
machine.pressButton();
machine.dispense();
System.out.println("\n【场景3:售罄后尝试购买】");
machine.insertCoin(); // 应该失败
}
}
2.2 交通信号灯 🚦
java
// 状态接口
interface TrafficLightState {
void change(TrafficLight light);
void showSignal();
}
// 具体状态
class RedLightState implements TrafficLightState {
@Override
public void change(TrafficLight light) {
System.out.println("红灯 → 绿灯");
light.setState(new GreenLightState());
}
@Override
public void showSignal() {
System.out.println("🔴 红灯:停止通行");
}
}
class GreenLightState implements TrafficLightState {
@Override
public void change(TrafficLight light) {
System.out.println("绿灯 → 黄灯");
light.setState(new YellowLightState());
}
@Override
public void showSignal() {
System.out.println("🟢 绿灯:可以通行");
}
}
class YellowLightState implements TrafficLightState {
@Override
public void change(TrafficLight light) {
System.out.println("黄灯 → 红灯");
light.setState(new RedLightState());
}
@Override
public void showSignal() {
System.out.println("🟡 黄灯:准备停止");
}
}
// 上下文
class TrafficLight {
private TrafficLightState state;
public TrafficLight() {
this.state = new RedLightState(); // 初始状态为红灯
}
public void setState(TrafficLightState state) {
this.state = state;
}
public void change() {
state.change(this);
}
public void show() {
state.showSignal();
}
}
// 测试
public class TrafficLightDemo {
public static void main(String[] args) throws InterruptedException {
TrafficLight light = new TrafficLight();
// 模拟交通灯循环
for (int i = 0; i < 6; i++) {
light.show();
Thread.sleep(1000);
light.change();
}
}
}
3. 归纳总结
3.1 状态模式核心总结 📊
| 要素 | 现实 | 类比 |
|---|---|---|
| Context(上下文) | 拥有状态的对象,维护当前状态 | 自动售货机本体 |
| State(状态接口) | 定义所有状态的共同行为规范 | "售货机状态"的职位描述 |
| ConcreteState(具体状态) | 实现特定状态下的行为 | 具体的"待机状态"、"出货状态"等 |
3.2 ✅ 状态模式的优点
- 单一职责原则:每个状态类只负责自己的行为
- 开闭原则:新增状态只需添加新类,无需修改已有代码
- 消除条件语句:用多态代替复杂的if-else或switch-case
- 状态转换明确:状态转移逻辑清晰可见
3.3 使用时机⚠️
当出现以下情况时考虑使用:
- 对象的行为取决于它的状态,并且必须在运行时根据状态改变行为
- 有大量的状态判断逻辑(if-else或switch)
- 状态之间有明确的转换关系
- 相似的状态和转换出现在多个地方
3.4 状态模式 vs 策略模式🔄
很多人容易混淆,关键区别:
- 状态模式:状态之间相互知道,会自动转换(红灯知道下一个是绿灯)
- 策略模式:策略之间相互独立,由客户端选择使用哪个策略
4. 补充知识💡
4.1 状态管理的方式
java
// 方式1:由Context管理状态转换(推荐)
class Order {
private OrderState state;
public void nextState() {
state = state.next(); // 状态类返回下一个状态
}
}
// 方式2:由具体状态类管理转换
class PaidState implements OrderState {
@Override
public OrderState next() {
return new ShippedState(); // 返回下一个状态实例
}
}
4.2 状态共享
如果状态是无状态的(不包含成员变量),可以共享同一个实例:
java
// 享元模式 + 状态模式
class StateFactory {
private static final Map<String, State> states = new HashMap<>();
static {
states.put("IDLE", new IdleState());
states.put("BUSY", new BusyState());
}
public static State getState(String key) {
return states.get(key);
}
}