状态模式详解
目录
- 状态模式简介
- 核心流程
- 重难点分析
- Spring中的源码分析
- 具体使用场景
- 面试高频点
- 使用总结
状态模式简介
定义
状态模式(State Pattern)是一种行为型设计模式,它允许对象在内部状态发生改变时改变它的行为,对象看起来好像修改了它的类。状态模式将状态封装成独立的类,并将动作委托到代表当前状态的对象。
核心思想
- 状态封装:将每个状态封装成独立的类
- 行为委托:将行为委托给当前状态对象
- 状态转换:通过状态对象管理状态转换
- 消除条件判断:用多态替代大量的条件判断
模式结构
- Context(环境类):定义客户感兴趣的接口,维护一个ConcreteState子类的实例
- State(抽象状态类):定义一个接口以封装与Context的一个特定状态相关的行为
- ConcreteState(具体状态类):实现抽象状态类,每一个子类实现一个与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;
}
}
面试高频点
面试知识点思维导图
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. 实际应用场景
问题:状态模式适用于哪些场景?
答案要点:
- 订单状态管理:订单的创建、确认、发货、送达等状态
- 游戏角色状态:角色的正常、防御、攻击等状态
- 工作流状态管理:工作流的审批、执行、完成等状态
- 系统状态控制:系统的启动、运行、停止等状态
使用总结
状态模式的优势
- 消除条件判断:用多态替代大量的条件判断
- 状态封装:将每个状态封装成独立的类
- 行为委托:将行为委托给当前状态对象
- 易于扩展:可以轻松添加新的状态
状态模式的缺点
- 复杂度增加:增加了系统的复杂度
- 状态转换:状态转换逻辑可能变得复杂
- 学习成本:需要理解状态模式的概念
- 过度设计:简单场景可能不需要使用
使用建议
- 复杂状态:只用于复杂的状态管理场景
- 状态转换:考虑状态转换的复杂性
- 并发安全:注意多线程环境下的状态安全
- 状态持久化:考虑状态的持久化需求
最佳实践
- 状态转换表:使用状态转换表管理复杂的状态转换
- 状态历史:记录状态转换的历史
- 并发安全:使用同步机制确保状态转换的线程安全
- 状态持久化:实现状态的持久化存储
- 单元测试:为状态模式编写完整的单元测试
与其他模式的对比
- 与策略模式:状态模式是状态转换,策略模式是算法选择
- 与命令模式:状态模式是状态管理,命令模式是请求封装
- 与观察者模式:状态模式是状态变化,观察者模式是状态通知
状态模式是一种有用的行为型设计模式,特别适用于需要管理复杂状态、消除条件判断、封装状态行为等场景。通过合理使用状态模式,可以大大提高代码的可维护性和可扩展性。