设计模式-状态模式详解
设计模式-状态模式详解
[
「开学季干货」:聚焦知识梳理与经验分享
10w+人浏览
831人参与
](
)
状态模式详解
目录
状态模式简介
定义
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。状态模式将状态封装成独立的类,并将动作委托到代表当前状态的对象。
核心思想
- 状态封装:将每个状态封装成独立的类
- 行为委托:将行为委托给当前状态对象
- 状态转换:通过状态对象管理状态转换
- 消除条件判断:用多态替代大量的条件判断
模式结构
- Context(环境类):定义客户感兴趣的接口,维护一个ConcreteState子类的实例
- State(抽象状态类):定义一个接口以封装与Context的一个特定状态相关的行为
- ConcreteState(具体状态类):实现抽象状态类,每一个子类实现一个与Context的一个状态相关的行为
核心流程
状态模式流程图
状态转换
状态类层次
环境类层次
是
否
状态A -> 状态B
状态B -> 状态C
状态C -> 状态A
State抽象状态
ConcreteStateA
ConcreteStateB
ConcreteStateC
Context环境类
状态引用
状态转换方法
客户端
创建环境对象
设置初始状态
调用环境对象方法
环境对象委托给当前状态
当前状态处理请求
是否需要状态转换?
状态对象执行状态转换
返回处理结果
更新环境对象状态
返回处理结果
客户端接收结果
基本实现流程
1. 定义抽象状态类
// 抽象状态类
public abstract class State {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
public abstract void handleRequest1();
public abstract void handleRequest2();
public abstract void handleRequest3();
// 状态转换方法
protected void changeState(State newState) {
context.changeState(newState);
}
}
2. 定义环境类
// 环境类
public class Context {
private State currentState;
public Context() {
// 设置初始状态
this.currentState = new ConcreteStateA();
this.currentState.setContext(this);
}
public void changeState(State newState) {
this.currentState = newState;
this.currentState.setContext(this);
System.out.println("状态转换到: " + newState.getClass().getSimpleName());
}
public void request1() {
currentState.handleRequest1();
}
public void request2() {
currentState.handleRequest2();
}
public void request3() {
currentState.handleRequest3();
}
public State getCurrentState() {
return currentState;
}
}
3. 实现具体状态类
// 具体状态A
public class ConcreteStateA extends State {
@Override
public void handleRequest1() {
System.out.println("状态A处理请求1");
// 状态A处理请求1的逻辑
}
@Override
public void handleRequest2() {
System.out.println("状态A处理请求2,转换到状态B");
changeState(new ConcreteStateB());
}
@Override
public void handleRequest3() {
System.out.println("状态A处理请求3,转换到状态C");
changeState(new ConcreteStateC());
}
}
// 具体状态B
public class ConcreteStateB extends State {
@Override
public void handleRequest1() {
System.out.println("状态B处理请求1,转换到状态A");
changeState(new ConcreteStateA());
}
@Override
public void handleRequest2() {
System.out.println("状态B处理请求2");
// 状态B处理请求2的逻辑
}
@Override
public void handleRequest3() {
System.out.println("状态B处理请求3,转换到状态C");
changeState(new ConcreteStateC());
}
}
// 具体状态C
public class ConcreteStateC extends State {
@Override
public void handleRequest1() {
System.out.println("状态C处理请求1,转换到状态A");
changeState(new ConcreteStateA());
}
@Override
public void handleRequest2() {
System.out.println("状态C处理请求2,转换到状态B");
changeState(new ConcreteStateB());
}
@Override
public void handleRequest3() {
System.out.println("状态C处理请求3");
// 状态C处理请求3的逻辑
}
}
4. 客户端使用
public class Client {
public static void main(String[] args) {
Context context = new Context();
// 初始状态是A
System.out.println("当前状态: " + context.getCurrentState().getClass().getSimpleName());
// 测试状态转换
context.request1(); // 状态A处理请求1
context.request2(); // 状态A -> 状态B
context.request2(); // 状态B处理请求2
context.request3(); // 状态B -> 状态C
context.request3(); // 状态C处理请求3
context.request1(); // 状态C -> 状态A
}
}
重难点分析
重难点1:状态转换的复杂性
问题描述
当状态转换逻辑复杂时,如何管理状态之间的转换关系。
解决方案
// 状态转换表
public class StateTransitionTable {
private final Map<State, Map<String, State>> transitions = new HashMap<>();
public void addTransition(State from, String event, State to) {
transitions.computeIfAbsent(from, k -> new HashMap<>()).put(event, to);
}
public State getNextState(State currentState, String event) {
Map<String, State> stateTransitions = transitions.get(currentState);
if (stateTransitions != null) {
return stateTransitions.get(event);
}
return null;
}
}
// 使用状态转换表的状态机
public class StateMachine {
private State currentState;
private final StateTransitionTable transitionTable;
public StateMachine(State initialState, StateTransitionTable transitionTable) {
this.currentState = initialState;
this.transitionTable = transitionTable;
this.currentState.setContext(this);
}
public void handleEvent(String event) {
State nextState = transitionTable.getNextState(currentState, event);
if (nextState != null) {
changeState(nextState);
} else {
System.out.println("无效的状态转换: " + currentState.getClass().getSimpleName() + " -> " + event);
}
}
private void changeState(State newState) {
this.currentState = newState;
this.currentState.setContext(this);
System.out.println("状态转换到: " + newState.getClass().getSimpleName());
}
}
// 状态转换规则
public class StateTransitionRules {
public static StateTransitionTable createOrderStateTransitionTable() {
StateTransitionTable table = new StateTransitionTable();
// 订单状态转换规则
OrderState pending = new OrderState("PENDING");
OrderState confirmed = new OrderState("CONFIRMED");
OrderState shipped = new OrderState("SHIPPED");
OrderState delivered = new OrderState("DELIVERED");
OrderState cancelled = new OrderState("CANCELLED");
// 添加转换规则
table.addTransition(pending, "CONFIRM", confirmed);
table.addTransition(pending, "CANCEL", cancelled);
table.addTransition(confirmed, "SHIP", shipped);
table.addTransition(confirmed, "CANCEL", cancelled);
table.addTransition(shipped, "DELIVER", delivered);
return table;
}
}
重难点2:状态的历史记录
问题描述
如何记录状态转换的历史,支持状态回滚和重放。
解决方案
// 状态历史记录
public class StateHistory {
private final List<StateRecord> history = new ArrayList<>();
private int currentIndex = -1;
public void addState(State state, String event) {
// 移除当前位置之后的所有记录
if (currentIndex < history.size() - 1) {
history.subList(currentIndex + 1, history.size()).clear();
}
StateRecord record = new StateRecord(state, event, System.currentTimeMillis());
history.add(record);
currentIndex = history.size() - 1;
}
public StateRecord getCurrentState() {
if (currentIndex >= 0 && currentIndex < history.size()) {
return history.get(currentIndex);
}
return null;
}
public StateRecord getPreviousState() {
if (currentIndex > 0) {
currentIndex--;
return history.get(currentIndex);
}
return null;
}
public StateRecord getNextState() {
if (currentIndex < history.size() - 1) {
currentIndex++;
return history.get(currentIndex);
}
return null;
}
public List<StateRecord> getHistory() {
return new ArrayList<>(history);
}
}
// 状态记录
public class StateRecord {
private final State state;
private final String event;
private final long timestamp;
public StateRecord(State state, String event, long timestamp) {
this.state = state;
this.event = event;
this.timestamp = timestamp;
}
// getter方法
public State getState() { return state; }
public String getEvent() { return event; }
public long getTimestamp() { return timestamp; }
}
// 支持历史记录的状态机
public class HistoricalStateMachine extends StateMachine {
private final StateHistory history;
public HistoricalStateMachine(State initialState, StateTransitionTable transitionTable) {
super(initialState, transitionTable);
this.history = new StateHistory();
this.history.addState(initialState, "INITIAL");
}
@Override
public void handleEvent(String event) {
State nextState = transitionTable.getNextState(currentState, event);
if (nextState != null) {
history.addState(nextState, event);
changeState(nextState);
} else {
System.out.println("无效的状态转换: " + currentState.getClass().getSimpleName() + " -> " + event);
}
}
public void rollback() {
StateRecord previousState = history.getPreviousState();
if (previousState != null) {
changeState(previousState.getState());
}
}
public void replay() {
StateRecord nextState = history.getNextState();
if (nextState != null) {
changeState(nextState.getState());
}
}
}
重难点3:状态的并发安全
问题描述
在多线程环境下,如何确保状态转换的线程安全。
解决方案
// 线程安全的状态机
public class ThreadSafeStateMachine {
private volatile State currentState;
private final Object stateLock = new Object();
private final StateTransitionTable transitionTable;
public ThreadSafeStateMachine(State initialState, StateTransitionTable transitionTable) {
this.currentState = initialState;
this.transitionTable = transitionTable;
this.currentState.setContext(this);
}
public void handleEvent(String event) {
synchronized (stateLock) {
State nextState = transitionTable.getNextState(currentState, event);
if (nextState != null) {
changeState(nextState);
} else {
System.out.println("无效的状态转换: " + currentState.getClass().getSimpleName() + " -> " + event);
}
}
}
private void changeState(State newState) {
this.currentState = newState;
this.currentState.setContext(this);
System.out.println("状态转换到: " + newState.getClass().getSimpleName());
}
public State getCurrentState() {
return currentState;
}
}
// 使用原子操作的状态机
public class AtomicStateMachine {
private final AtomicReference<State> currentState;
private final StateTransitionTable transitionTable;
public AtomicStateMachine(State initialState, StateTransitionTable transitionTable) {
this.currentState = new AtomicReference<>(initialState);
this.transitionTable = transitionTable;
this.currentState.get().setContext(this);
}
public void handleEvent(String event) {
State current = currentState.get();
State nextState = transitionTable.getNextState(current, event);
if (nextState != null) {
if (currentState.compareAndSet(current, nextState)) {
nextState.setContext(this);
System.out.println("状态转换到: " + nextState.getClass().getSimpleName());
} else {
// 状态已被其他线程修改,重试
handleEvent(event);
}
} else {
System.out.println("无效的状态转换: " + current.getClass().getSimpleName() + " -> " + event);
}
}
public State getCurrentState() {
return currentState.get();
}
}
重难点4:状态的持久化
问题描述
如何将状态信息持久化到数据库或文件中,支持系统重启后的状态恢复。
解决方案
// 状态持久化接口
public interface StatePersistence {
void saveState(String contextId, State state);
State loadState(String contextId);
void saveStateHistory(String contextId, List<StateRecord> history);
List<StateRecord> loadStateHistory(String contextId);
}
// 数据库状态持久化
public class DatabaseStatePersistence implements StatePersistence {
private final JdbcTemplate jdbcTemplate;
public DatabaseStatePersistence(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public void saveState(String contextId, State state) {
String sql = "INSERT INTO state_context (context_id, state_class, state_data, created_at) VALUES (?, ?, ?, ?) " +
"ON DUPLICATE KEY UPDATE state_class = ?, state_data = ?, updated_at = ?";
jdbcTemplate.update(sql, contextId, state.getClass().getName(),
serializeState(state), new Date(),
state.getClass().getName(), serializeState(state), new Date());
}
@Override
public State loadState(String contextId) {
String sql = "SELECT state_class, state_data FROM state_context WHERE context_id = ?";
try {
return jdbcTemplate.queryForObject(sql, (rs, rowNum) -> {
String stateClass = rs.getString("state_class");
String stateData = rs.getString("state_data");
return deserializeState(stateClass, stateData);
}, contextId);
} catch (EmptyResultDataAccessException e) {
return null;
}
}
private String serializeState(State state) {
// 序列化状态对象
return JSON.toJSONString(state);
}
private State deserializeState(String stateClass, String stateData) {
// 反序列化状态对象
try {
Class<?> clazz = Class.forName(stateClass);
return (State) JSON.parseObject(stateData, clazz);
} catch (ClassNotFoundException e) {
throw new RuntimeException("无法加载状态类: " + stateClass, e);
}
}
}
// 支持持久化的状态机
public class PersistentStateMachine extends StateMachine {
private final StatePersistence persistence;
private final String contextId;
public PersistentStateMachine(String contextId, State initialState,
StateTransitionTable transitionTable,
StatePersistence persistence) {
super(initialState, transitionTable);
this.contextId = contextId;
this.persistence = persistence;
// 尝试从持久化存储中恢复状态
State savedState = persistence.loadState(contextId);
if (savedState != null) {
this.currentState = savedState;
this.currentState.setContext(this);
}
}
@Override
public void handleEvent(String event) {
super.handleEvent(event);
// 保存状态到持久化存储
persistence.saveState(contextId, currentState);
}
}
Spring中的源码分析
Spring的状态机实现
// Spring StateMachine接口
public interface StateMachine<S, E> extends StateMachineAccessor<S, E> {
void start();
void stop();
boolean sendEvent(E event);
boolean sendEvent(Message<E> event);
void setStateMachineErrorHandler(StateMachineErrorHandler errorHandler);
void addStateListener(StateMachineListener<S, E> listener);
void removeStateListener(StateMachineListener<S, E> listener);
}
// Spring StateMachineConfigurer接口
public interface StateMachineConfigurer<S, E> {
void configure(StateMachineStateConfigurer<S, E> states) throws Exception;
void configure(StateMachineTransitionConfigurer<S, E> transitions) throws Exception;
void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception;
}
// Spring StateMachineBuilder
public class StateMachineBuilder<S, E> {
public static <S, E> StateMachineBuilder<S, E> builder() {
return new StateMachineBuilder<>();
}
public StateMachine<S, E> build() {
return new DefaultStateMachine<>(stateMachineModel, stateMachineAccessor);
}
public StateMachineBuilder<S, E> configure(StateMachineConfigurer<S, E> configurer) {
try {
configurer.configure(states);
configurer.configure(transitions);
configurer.configure(config);
} catch (Exception e) {
throw new StateMachineException("Error configuring state machine", e);
}
return this;
}
}
Spring的状态配置
// 状态配置
@Configuration
@EnableStateMachine
public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states
.withStates()
.initial("SI")
.state("S1")
.state("S2")
.end("SF");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal()
.source("SI").target("S1").event("E1")
.and()
.withExternal()
.source("S1").target("S2").event("E2")
.and()
.withExternal()
.source("S2").target("SF").event("E3");
}
}
// 状态机监听器
@Component
public class StateMachineListener implements StateMachineListener<String, String> {
@Override
public void stateChanged(State<String, String> from, State<String, String> to) {
System.out.println("状态转换: " + from.getId() + " -> " + to.getId());
}
@Override
public void stateEntered(State<String, String> state) {
System.out.println("进入状态: " + state.getId());
}
@Override
public void stateExited(State<String, String> state) {
System.out.println("退出状态: " + state.getId());
}
}
Spring的状态机使用
// 状态机服务
@Service
public class StateMachineService {
@Autowired
private StateMachine<String, String> stateMachine;
public void startStateMachine() {
stateMachine.start();
}
public void stopStateMachine() {
stateMachine.stop();
}
public boolean sendEvent(String event) {
return stateMachine.sendEvent(event);
}
public String getCurrentState() {
return stateMachine.getState().getId();
}
}
// 状态机控制器
@RestController
@RequestMapping("/statemachine")
public class StateMachineController {
@Autowired
private StateMachineService stateMachineService;
@PostMapping("/start")
public ResponseEntity<String> start() {
stateMachineService.startStateMachine();
return ResponseEntity.ok("状态机已启动");
}
@PostMapping("/stop")
public ResponseEntity<String> stop() {
stateMachineService.stopStateMachine();
return ResponseEntity.ok("状态机已停止");
}
@PostMapping("/event")
public ResponseEntity<String> sendEvent(@RequestParam String event) {
boolean result = stateMachineService.sendEvent(event);
if (result) {
return ResponseEntity.ok("事件发送成功,当前状态: " + stateMachineService.getCurrentState());
} else {
return ResponseEntity.badRequest().body("事件发送失败");
}
}
}
具体使用场景
1. 订单状态管理
// 订单状态枚举
public enum OrderStatus {
PENDING("待处理"),
CONFIRMED("已确认"),
SHIPPED("已发货"),
DELIVERED("已送达"),
CANCELLED("已取消");
private final String description;
OrderStatus(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
// 订单状态机
public class OrderStateMachine {
private OrderStatus currentStatus;
private final Order order;
public OrderStateMachine(Order order) {
this.order = order;
this.currentStatus = OrderStatus.PENDING;
}
public boolean confirm() {
if (currentStatus == OrderStatus.PENDING) {
currentStatus = OrderStatus.CONFIRMED;
order.setStatus(currentStatus);
order.setConfirmedAt(new Date());
return true;
}
return false;
}
public boolean ship() {
if (currentStatus == OrderStatus.CONFIRMED) {
currentStatus = OrderStatus.SHIPPED;
order.setStatus(currentStatus);
order.setShippedAt(new Date());
return true;
}
return false;
}
public boolean deliver() {
if (currentStatus == OrderStatus.SHIPPED) {
currentStatus = OrderStatus.DELIVERED;
order.setStatus(currentStatus);
order.setDeliveredAt(new Date());
return true;
}
return false;
}
public boolean cancel() {
if (currentStatus == OrderStatus.PENDING || currentStatus == OrderStatus.CONFIRMED) {
currentStatus = OrderStatus.CANCELLED;
order.setStatus(currentStatus);
order.setCancelledAt(new Date());
return true;
}
return false;
}
public OrderStatus getCurrentStatus() {
return currentStatus;
}
}
// 订单类
public class Order {
private String id;
private String customerId;
private List<OrderItem> items;
private OrderStatus status;
private Date createdAt;
private Date confirmedAt;
private Date shippedAt;
private Date deliveredAt;
private Date cancelledAt;
// 构造函数、getter和setter方法
public Order(String id, String customerId, List<OrderItem> items) {
this.id = id;
this.customerId = customerId;
this.items = items;
this.status = OrderStatus.PENDING;
this.createdAt = new Date();
}
// getter和setter方法
public String getId() { return id; }
public String getCustomerId() { return customerId; }
public List<OrderItem> getItems() { return items; }
public OrderStatus getStatus() { return status; }
public void setStatus(OrderStatus status) { this.status = status; }
public Date getCreatedAt() { return createdAt; }
public Date getConfirmedAt() { return confirmedAt; }
public void setConfirmedAt(Date confirmedAt) { this.confirmedAt = confirmedAt; }
public Date getShippedAt() { return shippedAt; }
public void setShippedAt(Date shippedAt) { this.shippedAt = shippedAt; }
public Date getDeliveredAt() { return deliveredAt; }
public void setDeliveredAt(Date deliveredAt) { this.deliveredAt = deliveredAt; }
public Date getCancelledAt() { return cancelledAt; }
public void setCancelledAt(Date cancelledAt) { this.cancelledAt = cancelledAt; }
}
2. 游戏角色状态
// 游戏角色状态接口
public interface CharacterState {
void move(Character character);
void attack(Character character);
void defend(Character character);
void useSkill(Character character, String skill);
}
// 正常状态
public class NormalState implements CharacterState {
@Override
public void move(Character character) {
System.out.println(character.getName() + " 正常移动");
character.setPosition(character.getPosition() + 1);
}
@Override
public void attack(Character character) {
System.out.println(character.getName() + " 发起攻击");
character.setHealth(character.getHealth() - 10);
}
@Override
public void defend(Character character) {
System.out.println(character.getName() + " 进入防御状态");
character.setState(new DefendingState());
}
@Override
public void useSkill(Character character, String skill) {
System.out.println(character.getName() + " 使用技能: " + skill);
character.setMana(character.getMana() - 20);
}
}
// 防御状态
public class DefendingState implements CharacterState {
@Override
public void move(Character character) {
System.out.println(character.getName() + " 防御状态下移动缓慢");
character.setPosition(character.getPosition() + 0.5);
}
@Override
public void attack(Character character) {
System.out.println(character.getName() + " 防御状态下无法攻击");
}
@Override
public void defend(Character character) {
System.out.println(character.getName() + " 继续防御");
}
@Override
public void useSkill(Character character, String skill) {
System.out.println(character.getName() + " 防御状态下无法使用技能");
}
}
// 游戏角色类
public class Character {
private String name;
private int health;
private int mana;
private double position;
private CharacterState state;
public Character(String name) {
this.name = name;
this.health = 100;
this.mana = 100;
this.position = 0;
this.state = new NormalState();
}
public void move() {
state.move(this);
}
public void attack() {
state.attack(this);
}
public void defend() {
state.defend(this);
}
public void useSkill(String skill) {
state.useSkill(this, skill);
}
// getter和setter方法
public String getName() { return name; }
public int getHealth() { return health; }
public void setHealth(int health) { this.health = health; }
public int getMana() { return mana; }
public void setMana(int mana) { this.mana = mana; }
public double getPosition() { return position; }
public void setPosition(double position) { this.position = position; }
public CharacterState getState() { return state; }
public void setState(CharacterState state) { this.state = state; }
}
3. 工作流状态管理
// 工作流状态接口
public interface WorkflowState {
void process(WorkflowContext context);
boolean canTransitionTo(WorkflowState nextState);
}
// 待审批状态
public class PendingApprovalState implements WorkflowState {
@Override
public void process(WorkflowContext context) {
System.out.println("工作流处于待审批状态");
// 发送审批通知
sendApprovalNotification(context);
}
@Override
public boolean canTransitionTo(WorkflowState nextState) {
return nextState instanceof ApprovedState || nextState instanceof RejectedState;
}
private void sendApprovalNotification(WorkflowContext context) {
System.out.println("发送审批通知给: " + context.getApprover());
}
}
// 已审批状态
public class ApprovedState implements WorkflowState {
@Override
public void process(WorkflowContext context) {
System.out.println("工作流已审批通过");
// 执行后续流程
executeNextStep(context);
}
@Override
public boolean canTransitionTo(WorkflowState nextState) {
return nextState instanceof InProgressState || nextState instanceof CompletedState;
}
private void executeNextStep(WorkflowContext context) {
System.out.println("执行下一步: " + context.getNextStep());
}
}
// 工作流上下文
public class WorkflowContext {
private String workflowId;
private String currentStep;
private String nextStep;
private String approver;
private Map<String, Object> data;
public WorkflowContext(String workflowId) {
this.workflowId = workflowId;
this.data = new HashMap<>();
}
// getter和setter方法
public String getWorkflowId() { return workflowId; }
public String getCurrentStep() { return currentStep; }
public void setCurrentStep(String currentStep) { this.currentStep = currentStep; }
public String getNextStep() { return nextStep; }
public void setNextStep(String nextStep) { this.nextStep = nextStep; }
public String getApprover() { return approver; }
public void setApprover(String approver) { this.approver = approver; }
public Map<String, Object> getData() { return data; }
public void setData(Map<String, Object> data) { this.data = data; }
}
面试高频点
面试知识点思维导图
状态模式面试点
基本概念
实现方式
重难点
Spring应用
设计原则
实际应用
状态封装
行为委托
状态转换
消除条件判断
Context环境类
State抽象状态类
ConcreteState具体状态类
状态转换逻辑
状态转换复杂性
状态历史记录
并发安全
状态持久化
Spring StateMachine
状态配置
状态监听器
状态机服务
单一职责
开闭原则
依赖倒置
接口隔离
订单状态管理
游戏角色状态
工作流状态管理
系统状态控制
1. 状态模式的基本概念
问题:什么是状态模式?
答案要点:
- 允许对象在内部状态发生改变时改变它的行为
- 对象看起来好像修改了它的类
- 将状态封装成独立的类,并将动作委托到代表当前状态的对象
- 属于行为型设计模式
问题:状态模式有哪些角色?
答案要点:
- Context(环境类):定义客户感兴趣的接口,维护一个ConcreteState子类的实例
- State(抽象状态类):定义一个接口以封装与Context的一个特定状态相关的行为
- ConcreteState(具体状态类):实现抽象状态类,每一个子类实现一个与Context的一个状态相关的行为
2. 实现方式相关
问题:如何实现状态模式?
答案要点:
// 1. 定义抽象状态类
public abstract class State {
protected Context context;
public void setContext(Context context) {
this.context = context;
}
public abstract void handleRequest();
}
// 2. 定义环境类
public class Context {
private State currentState;
public void changeState(State newState) {
this.currentState = newState;
this.currentState.setContext(this);
}
public void request() {
currentState.handleRequest();
}
}
// 3. 实现具体状态类
public class ConcreteStateA extends State {
@Override
public void handleRequest() {
System.out.println("状态A处理请求");
context.changeState(new ConcreteStateB());
}
}
3. 重难点问题
问题:状态模式与策略模式的区别?
答案要点:
- 目的:状态模式是处理状态转换,策略模式是选择算法
- 状态:状态模式有状态转换,策略模式没有状态
- 耦合度:状态模式耦合度更高,策略模式耦合度更低
- 使用场景:状态模式用于状态管理,策略模式用于算法选择
问题:如何解决状态转换的复杂性问题?
答案要点:
// 1. 使用状态转换表
public class StateTransitionTable {
private final Map<State, Map<String, State>> transitions = new HashMap<>();
public void addTransition(State from, String event, State to) {
transitions.computeIfAbsent(from, k -> new HashMap<>()).put(event, to);
}
public State getNextState(State currentState, String event) {
Map<String, State> stateTransitions = transitions.get(currentState);
if (stateTransitions != null) {
return stateTransitions.get(event);
}
return null;
}
}
// 2. 使用状态机模式
public class StateMachine {
private State currentState;
private final StateTransitionTable transitionTable;
public void handleEvent(String event) {
State nextState = transitionTable.getNextState(currentState, event);
if (nextState != null) {
changeState(nextState);
}
}
}
4. Spring中的应用
问题:Spring中如何使用状态模式?
答案要点:
// 1. 使用Spring StateMachine
@Configuration
@EnableStateMachine
public class StateMachineConfig extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineStateConfigurer<String, String> states) throws Exception {
states
.withStates()
.initial("SI")
.state("S1")
.state("S2")
.end("SF");
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions) throws Exception {
transitions
.withExternal()
.source("SI").target("S1").event("E1")
.and()
.withExternal()
.source("S1").target("S2").event("E2");
}
}
// 2. 使用状态机服务
@Service
public class StateMachineService {
@Autowired
private StateMachine<String, String> stateMachine;
public boolean sendEvent(String event) {
return stateMachine.sendEvent(event);
}
}
5. 设计原则相关
问题:状态模式体现了哪些设计原则?
答案要点:
- 单一职责:每个状态类只负责一个状态的行为
- 开闭原则:可以添加新的状态而不修改现有代码
- 依赖倒置:依赖抽象而不是具体实现
- 接口隔离:客户端只依赖需要的接口
6. 实际应用场景
问题:状态模式适用于哪些场景?
答案要点:
- 订单状态管理:订单的创建、确认、发货、送达等状态
- 游戏角色状态:角色的正常、防御、攻击等状态
- 工作流状态管理:工作流的审批、执行、完成等状态
- 系统状态控制:系统的启动、运行、停止等状态
使用总结
状态模式的优势
- 消除条件判断:用多态替代大量的条件判断
- 状态封装:将每个状态封装成独立的类
- 行为委托:将行为委托给当前状态对象
- 易于扩展:可以轻松添加新的状态
状态模式的缺点
- 复杂度增加:增加了系统的复杂度
- 状态转换:状态转换逻辑可能变得复杂
- 学习成本:需要理解状态模式的概念
- 过度设计:简单场景可能不需要使用
使用建议
- 复杂状态:只用于复杂的状态管理场景
- 状态转换:考虑状态转换的复杂性
- 并发安全:注意多线程环境下的状态安全
- 状态持久化:考虑状态的持久化需求
最佳实践
- 状态转换表:使用状态转换表管理复杂的状态转换
- 状态历史:记录状态转换的历史
- 并发安全:使用同步机制确保状态转换的线程安全
- 状态持久化:实现状态的持久化存储
- 单元测试:为状态模式编写完整的单元测试
与其他模式的对比
- 与策略模式:状态模式是状态转换,策略模式是算法选择
- 与命令模式:状态模式是状态管理,命令模式是请求封装
- 与观察者模式:状态模式是状态变化,观察者模式是状态通知
状态模式是一种有用的行为型设计模式,特别适用于需要管理复杂状态、消除条件判断、封装状态行为等场景。通过合理使用状态模式,可以大大提高代码的可维护性和可扩展性。