0126_状态模式(State)

状态模式(State)

意图

允许对象在内部状态改变时改变它的行为。对象看起来似乎修改了它的类。

UML 图

State

优点

  1. 行为与状态绑定:将特定状态下的行为局部化到对应的状态类中
  2. 消除条件判断:避免了大量的if-else状态判断逻辑
  3. 状态转换明确:使状态转换流程更加清晰和可管理
  4. 易于扩展:新增日常状态不需要修改现有代码
  5. 职责分离:每个状态类只关注自己的行为,符合单一职责原则

缺点

  1. 类数量增加:每个日常状态都需要一个具体的状态类
  2. 状态转换逻辑:状态转换可能需要在多个类中维护
  3. 上下文依赖:状态类需要了解上下文信息
  4. 初始化复杂:对于简单的状态机可能显得过于复杂
  5. 性能考虑:频繁的状态切换可能带来性能开销

代码示例

以人类一天的不同状态(睡眠-->起床-->吃饭-->运动-->睡眠)为例:

1. 状态接口 (State Interface)

// 日常状态接口
public interface DailyState {
    void handle(Person person);
    String getStateName();
    void performAction();
}

2. 上下文 (Context) - 人类

// 上下文 - 人类
public class Person {
    private DailyState currentState;
    private String name;
    private int energyLevel; // 能量级别
    
    public Person(String name) {
        this.name = name;
        this.energyLevel = 100; // 初始能量满格
        this.currentState = new SleepingState(); // 默认睡眠状态
    }
    
    public void setState(DailyState state) {
        this.currentState = state;
        System.out.println("🌞 " + name + " 进入状态: " + state.getStateName());
    }
    
    public void performCurrentAction() {
        System.out.print("👤 " + name + " ");
        currentState.performAction();
    }
    
    public void handleDailyRoutine() {
        currentState.handle(this);
    }
    
    public void consumeEnergy(int amount) {
        energyLevel -= amount;
        System.out.println("⚡ 能量消耗: " + amount + ", 剩余能量: " + energyLevel);
    }
    
    public void restoreEnergy(int amount) {
        energyLevel += amount;
        if (energyLevel > 100) energyLevel = 100;
        System.out.println("🔋 能量恢复: " + amount + ", 当前能量: " + energyLevel);
    }
    
    public int getEnergyLevel() {
        return energyLevel;
    }
    
    public String getName() {
        return name;
    }
    
    public DailyState getCurrentState() {
        return currentState;
    }
    
    // 开始新的一天
    public void startDay() {
        System.out.println("\n=== " + name + " 开始新的一天 ===");
        handleDailyRoutine();
    }
}

3. 具体状态 (Concrete States)

// 睡眠状态
public class SleepingState implements DailyState {
    @Override
    public void handle(Person person) {
        if (person.getEnergyLevel() < 30) {
            System.out.println("😴 " + person.getName() + " 能量不足,需要睡觉恢复");
            person.restoreEnergy(70);
            // 睡醒后转换为起床状态
            person.setState(new WakingUpState());
        } else {
            System.out.println("⏰ " + person.getName() + " 已经休息够了,该起床了");
            person.setState(new WakingUpState());
        }
    }
    
    @Override
    public String getStateName() {
        return "睡眠中";
    }
    
    @Override
    public void performAction() {
        System.out.println("正在睡觉... 💤");
    }
}

// 起床状态
public class WakingUpState implements DailyState {
    @Override
    public void handle(Person person) {
        System.out.println("☀️ " + person.getName() + " 醒来,开始新的一天");
        person.consumeEnergy(10); // 起床消耗能量
        // 起床后需要吃饭
        person.setState(new EatingState());
    }
    
    @Override
    public String getStateName() {
        return "起床中";
    }
    
    @Override
    public void performAction() {
        System.out.println("正在起床,伸个懒腰... 🛏️");
    }
}

// 吃饭状态
public class EatingState implements DailyState {
    @Override
    public void handle(Person person) {
        System.out.println("🍽️ " + person.getName() + " 开始用餐");
        person.restoreEnergy(40); // 吃饭恢复能量
        person.consumeEnergy(5);  // 吃饭也消耗少量能量
        
        // 根据能量水平决定下一个状态
        if (person.getEnergyLevel() > 80) {
            System.out.println("👍 " + person.getName() + " 能量充足,可以开始活动");
            // 这里可以转换为工作或活动状态
            person.setState(new SleepingState()); // 简化示例,回到睡眠
        } else {
            System.out.println("😴 " + person.getName() + " 还需要休息");
            person.setState(new SleepingState());
        }
    }
    
    @Override
    public String getStateName() {
        return "用餐中";
    }
    
    @Override
    public void performAction() {
        System.out.println("正在享受美食... 🍎");
    }
}

// 活动状态(扩展示例)
public class ActivityState implements DailyState {
    @Override
    public void handle(Person person) {
        System.out.println("🏃 " + person.getName() + " 开始活动");
        person.consumeEnergy(30);
        
        if (person.getEnergyLevel() < 40) {
            System.out.println("🍽️ " + person.getName() + " 能量低,需要吃饭");
            person.setState(new EatingState());
        } else if (person.getEnergyLevel() < 20) {
            System.out.println("😴 " + person.getName() + " 太累了,需要睡觉");
            person.setState(new SleepingState());
        }
    }
    
    @Override
    public String getStateName() {
        return "活动中";
    }
    
    @Override
    public void performAction() {
        System.out.println("正在进行日常活动... 🏋️");
    }
}

4. 状态转换管理器

// 日常状态管理器
public class DailyStateManager {
    public static void simulateDay(Person person) {
        System.out.println("\n📅 模拟 " + person.getName() + " 的一天");
        
        // 初始状态:睡眠
        person.setState(new SleepingState());
        person.performCurrentAction();
        person.handleDailyRoutine();
        
        // 起床
        person.performCurrentAction();
        person.handleDailyRoutine();
        
        // 吃饭
        person.performCurrentAction();
        person.handleDailyRoutine();
        
        // 再次睡眠,完成一天循环
        person.performCurrentAction();
        person.handleDailyRoutine();
        
        System.out.println("🌙 " + person.getName() + " 的一天结束了");
    }
    
    public static void simulateMultipleDays(Person person, int days) {
        for (int i = 1; i <= days; i++) {
            System.out.println("\n========== 第 " + i + " 天 ==========");
            simulateDay(person);
        }
    }
}

5. 客户端代码

public class StatePatternDemo {
    public static void main(String[] args) {
        // 创建人类对象
        Person person = new Person("小明");
        
        System.out.println("=== 个人状态模拟 ===");
        System.out.println("初始能量: " + person.getEnergyLevel());
        
        // 模拟一天的生活
        DailyStateManager.simulateDay(person);
        
        System.out.println("\n=== 多天模拟 ===");
        Person anotherPerson = new Person("小红");
        DailyStateManager.simulateMultipleDays(anotherPerson, 3);
        
        System.out.println("\n=== 手动状态控制 ===");
        Person manualPerson = new Person("手动控制者");
        
        // 手动设置状态
        manualPerson.setState(new SleepingState());
        manualPerson.performCurrentAction();
        manualPerson.handleDailyRoutine();
        
        manualPerson.setState(new WakingUpState());
        manualPerson.performCurrentAction();
        manualPerson.handleDailyRoutine();
        
        manualPerson.setState(new EatingState());
        manualPerson.performCurrentAction();
        manualPerson.handleDailyRoutine();
        
        System.out.println("最终能量: " + manualPerson.getEnergyLevel());
    }
}

在Java标准库中的应用

状态模式在Java标准库中的类似应用:

  1. 生命周期管理
// Servlet 生命周期状态管理
public interface Servlet {
    void init(ServletConfig config);    // 初始化状态
    void service(...);                 // 运行状态
    void destroy();                    // 销毁状态
}
  1. 线程状态管理
// Thread 状态枚举
Thread thread = new Thread();
Thread.State state = thread.getState();
// 状态包括: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
  1. 工作流状态
// 各种工作流框架中的状态管理
// 如订单状态:待支付、已支付、已发货、已完成等
  1. 游戏角色状态
// 游戏开发中的角色状态管理
// 如:站立、行走、奔跑、跳跃、攻击、受伤等状态

总结

状态模式通过将人类一天中的不同行为状态(起床、吃饭、睡觉)封装成独立的状态类,使得状态转换和行为变化更加清晰和易于管理。每个状态类只关注自己在特定状态下的行为,避免了复杂的条件判断逻辑。这种模式特别适合用于那些有明确状态转换流程的场景,如日常生活规律、工作流程、游戏状态管理等。通过状态模式,我们可以轻松地扩展新的日常状态(如工作、娱乐等),而不需要修改现有的状态管理逻辑。

posted @ 2025-09-12 07:57  庞去广  阅读(15)  评论(0)    收藏  举报