目录
-
- 一、初阶:红绿灯的哲学课
- 二、状态模式的四种修炼境界
-
- [2.1 经典流派------面向对象式](#2.1 经典流派——面向对象式)
- [2.2 枚举派------消灭类爆炸](#2.2 枚举派——消灭类爆炸)
- [2.3 Spring流------依赖注入的艺术](#2.3 Spring流——依赖注入的艺术)
- [2.4 现代派------记录类+Lambda](#2.4 现代派——记录类+Lambda)
- 三、实战:电商订单的七十二变
- 四、高阶技巧:状态机的N种打开方式
-
- [4.1 状态+策略模式](#4.1 状态+策略模式)
- [4.2 状态持久化](#4.2 状态持久化)
- 五、最佳实践与防坑指南
- 六、扩展思考:游戏开发中的状态魔法
"我的对象就像川剧演员------在不同状态下能瞬间切换不同行为,这可比只会if-else的呆瓜强多了!" ------ 来自资深程序员的奇妙比喻
一、初阶:红绿灯的哲学课
假设我们要实现一个交通信号灯系统,新手可能会写出这样的代码:
java
public class TrafficLight {
private String state = "RED";
public void change() {
if ("RED".equals(state)) {
state = "GREEN";
System.out.println("绿灯通行");
} else if ("GREEN".equals(state)) {
state = "YELLOW";
System.out.println("黄灯减速");
} else if ("YELLOW".equals(state)) {
state = "RED";
System.out.println("红灯停车");
}
}
}
痛点警报:当需要新增"闪烁黄灯"状态时,需要修改所有判断逻辑,这就像在已经建好的大楼里加装电梯------风险高、难度大!
二、状态模式的四种修炼境界
2.1 经典流派------面向对象式
java
// 状态接口
interface TrafficState {
void handle(TrafficLight light);
}
// 具体状态类
class RedState implements TrafficState {
public void handle(TrafficLight light) {
System.out.println("红灯停车");
light.setState(new GreenState());
}
}
class GreenState implements TrafficState {
public void handle(TrafficLight light) {
System.out.println("绿灯通行");
light.setState(new YellowState());
}
}
// 上下文类
class TrafficLight {
private TrafficState state = new RedState();
public void setState(TrafficState state) {
this.state = state;
}
public void change() {
state.handle(this);
}
}
// 使用示例
TrafficLight light = new TrafficLight();
light.change(); // 红灯 -> 绿灯
light.change(); // 绿灯 -> 黄灯
2.2 枚举派------消灭类爆炸
java
public enum ElevatorState {
STOPPED {
public void move(Elevator elevator) {
System.out.println("电梯启动");
elevator.setState(MOVING_UP);
}
},
MOVING_UP {
public void move(Elevator elevator) {
System.out.println("到达顶层");
elevator.setState(MOVING_DOWN);
}
},
MOVING_DOWN {
public void move(Elevator elevator) {
System.out.println("到达底层");
elevator.setState(STOPPED);
}
};
public abstract void move(Elevator elevator);
}
class Elevator {
private ElevatorState state = ElevatorState.STOPPED;
public void setState(ElevatorState state) {
this.state = state;
}
public void call() {
state.move(this);
}
}
2.3 Spring流------依赖注入的艺术
java
public interface DocumentState {
void review(Document document);
}
@Component
class DraftState implements DocumentState {
public void review(Document document) {
if (validationPassed()) {
document.setState(applicationContext.getBean(ReviewedState.class));
}
}
}
@Service
class Document {
@Autowired
private ApplicationContext applicationContext;
private DocumentState state;
public void review() {
state.review(this);
}
}
2.4 现代派------记录类+Lambda
java
public class MediaPlayer {
record PlayState(Runnable onPlay) implements State {}
record PauseState(Runnable onPause) implements State {}
interface State {
default void play(MediaPlayer player) {}
default void pause(MediaPlayer player) {}
}
private State state = new PauseState(() ->
System.out.println("播放暂停中"));
public void play() {
state.play(this);
}
void changeState(State newState) {
this.state = newState;
}
}
三、实战:电商订单的七十二变
java
public class Order {
private OrderState state = new NewState();
public void pay() {
state.pay(this);
}
// 状态切换方法
void setState(OrderState state) {
this.state = state;
}
}
interface OrderState {
default void pay(Order order) {
throw new IllegalStateException("当前状态不支持支付");
}
// 其他操作方法...
}
class NewState implements OrderState {
public void pay(Order order) {
System.out.println("支付成功");
order.setState(new PaidState());
}
}
class PaidState implements OrderState {
public void ship(Order order) {
System.out.println("开始发货");
order.setState(new ShippedState());
}
}
四、高阶技巧:状态机的N种打开方式
4.1 状态+策略模式
java
public class GameCharacter {
private State state = new NormalState();
public void attack() {
state.attack().execute();
}
}
interface State {
Command attack();
Command defend();
}
class BerserkState implements State {
public Command attack() {
return () -> System.out.println("狂暴攻击!伤害+50%");
}
}
4.2 状态持久化
java
public class Workflow {
@Enumerated(EnumType.STRING)
private StateType currentState;
@Transient // 不持久化
private State state;
@PostLoad
void initializeState() {
this.state = StateFactory.getState(currentState);
}
}
enum StateType { DRAFT, APPROVAL, COMPLETED }
五、最佳实践与防坑指南
✅ 使用场景:
- 对象需要根据状态改变行为
- 需要替代复杂的条件判断
- 状态转换逻辑明确
- 需要清晰的状态隔离
💥 避坑要点:
- 避免上帝状态(单个状态类过于庞大)
- 注意线程安全问题(状态对象的可变性)
- 谨慎处理状态迁移的副作用
- 考虑状态对象的创建成本
倒计时结束 倒计时结束 倒计时结束 Red Green 按钮按下 30秒后 Walk Wait Yellow
六、扩展思考:游戏开发中的状态魔法
实现一个超级马里奥的状态系统:
java
public class Mario {
private MarioState state = new SmallState();
public void takeMushroom() {
state = state.takeMushroom();
}
public void takeFireFlower() {
state = state.takeFireFlower();
}
}
interface MarioState {
MarioState takeMushroom();
MarioState takeFireFlower();
default void attack() {
System.out.println("跳跃攻击");
}
}
class FireMario implements MarioState {
public MarioState takeMushroom() {
return this; // 形态不变
}
public void attack() {
System.out.println("发射火球!");
}
}
终极挑战:如果我们要实现一个智能咖啡机的状态系统(待机、磨豆、冲泡、清洁、故障状态),你会如何设计状态之间的转换关系?欢迎在评论区留下你的设计方案!