0126_状态模式(State)
状态模式(State)
意图
允许对象在内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
UML 图

优点
- 行为与状态绑定:将特定状态下的行为局部化到对应的状态类中
- 消除条件判断:避免了大量的if-else状态判断逻辑
- 状态转换明确:使状态转换流程更加清晰和可管理
- 易于扩展:新增日常状态不需要修改现有代码
- 职责分离:每个状态类只关注自己的行为,符合单一职责原则
缺点
- 类数量增加:每个日常状态都需要一个具体的状态类
- 状态转换逻辑:状态转换可能需要在多个类中维护
- 上下文依赖:状态类需要了解上下文信息
- 初始化复杂:对于简单的状态机可能显得过于复杂
- 性能考虑:频繁的状态切换可能带来性能开销
代码示例
以人类一天的不同状态(睡眠-->起床-->吃饭-->运动-->睡眠)为例:
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标准库中的类似应用:
- 生命周期管理
// Servlet 生命周期状态管理
public interface Servlet {
void init(ServletConfig config); // 初始化状态
void service(...); // 运行状态
void destroy(); // 销毁状态
}
- 线程状态管理
// Thread 状态枚举
Thread thread = new Thread();
Thread.State state = thread.getState();
// 状态包括: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
- 工作流状态
// 各种工作流框架中的状态管理
// 如订单状态:待支付、已支付、已发货、已完成等
- 游戏角色状态
// 游戏开发中的角色状态管理
// 如:站立、行走、奔跑、跳跃、攻击、受伤等状态
总结
状态模式通过将人类一天中的不同行为状态(起床、吃饭、睡觉)封装成独立的状态类,使得状态转换和行为变化更加清晰和易于管理。每个状态类只关注自己在特定状态下的行为,避免了复杂的条件判断逻辑。这种模式特别适合用于那些有明确状态转换流程的场景,如日常生活规律、工作流程、游戏状态管理等。通过状态模式,我们可以轻松地扩展新的日常状态(如工作、娱乐等),而不需要修改现有的状态管理逻辑。

浙公网安备 33010602011771号