20.万物皆可变身术:状态模式架构全景解析

目录

"我的对象就像川剧演员------在不同状态下能瞬间切换不同行为,这可比只会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 }

五、最佳实践与防坑指南

使用场景

  • 对象需要根据状态改变行为
  • 需要替代复杂的条件判断
  • 状态转换逻辑明确
  • 需要清晰的状态隔离

💥 避坑要点

  1. 避免上帝状态(单个状态类过于庞大)
  2. 注意线程安全问题(状态对象的可变性)
  3. 谨慎处理状态迁移的副作用
  4. 考虑状态对象的创建成本

倒计时结束 倒计时结束 倒计时结束 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("发射火球!");
    }
}

终极挑战:如果我们要实现一个智能咖啡机的状态系统(待机、磨豆、冲泡、清洁、故障状态),你会如何设计状态之间的转换关系?欢迎在评论区留下你的设计方案!

相关推荐
苹果醋323 分钟前
React Native jpush-react-native极光推送 iOS生产环境接收不到推送
java·运维·spring boot·mysql·nginx
老华带你飞29 分钟前
数码论坛|基于SprinBoot+vue的数码论坛系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·数码论坛系统
葵野寺40 分钟前
【JVM】深入解析Java虚拟机
java·linux·jvm·gc·垃圾回收
程序猿七度1 小时前
【FastExcel】解决ReadSheet在Map中获取对象不准确问题(已提交PR并合并到开源社区)
java·开源·fastexcel
AI风老师2 小时前
5、docker镜像管理命令
java·docker·eureka
用户84913717547162 小时前
JustAuth实战系列(第5期):建造者模式进阶 - AuthRequestBuilder设计解析
java·设计模式·架构
励志成为糕手3 小时前
从反射到方法句柄:深入探索Java动态编程的终极解决方案
java·开发语言
是乐谷3 小时前
饿了么招java开发咯
java·开发语言·人工智能·程序人生·面试·职场和发展
hongjunwu3 小时前
Java集合的遍历方式(全解析)
java·开发语言·windows