【设计模式手册019】状态模式 - 管理对象状态转换

【设计模式手册019】状态模式 - 管理对象状态转换

本文是「设计模式手册」系列第019篇,我将以深入浅出、追本溯源的风格,带你真正理解状态模式的精髓。

1. 我们为何需要状态模式?

在软件设计中,我们经常会遇到这样的场景:对象的行为取决于它的状态,并且需要在运行时根据状态改变行为。比如:

  • 订单系统:待支付、已支付、已发货、已完成、已取消
  • 电梯控制:停止、运行、开门、关门、故障
  • 游戏角色:正常、中毒、眩晕、死亡、无敌
  • 工作流引擎:草稿、审批中、已批准、已拒绝

初级程序员的写法

java 复制代码
public class Order {
    private String state;
    
    public void process() {
        if ("PENDING_PAYMENT".equals(state)) {
            // 待支付状态的处理逻辑
            System.out.println("处理支付...");
            state = "PAID";
        } else if ("PAID".equals(state)) {
            // 已支付状态的处理逻辑
            System.out.println("准备发货...");
            state = "SHIPPED";
        } else if ("SHIPPED".equals(state)) {
            // 已发货状态的处理逻辑
            System.out.println("等待确认收货...");
            state = "COMPLETED";
        } else if ("COMPLETED".equals(state)) {
            // 已完成状态的处理逻辑
            System.out.println("订单已完成,无法继续处理");
        } else if ("CANCELLED".equals(state)) {
            // 已取消状态的处理逻辑
            System.out.println("订单已取消,无法处理");
        }
        // 每新增一个状态,这里就要加一个else if
    }
    
    public void cancel() {
        if ("PENDING_PAYMENT".equals(state)) {
            // 待支付状态的取消逻辑
            System.out.println("取消待支付订单...");
            state = "CANCELLED";
        } else if ("PAID".equals(state)) {
            // 已支付状态的取消逻辑
            System.out.println("取消已支付订单,需要退款...");
            state = "CANCELLED";
        } else if ("SHIPPED".equals(state)) {
            // 已发货状态的取消逻辑
            System.out.println("订单已发货,无法取消");
        } else if ("COMPLETED".equals(state)) {
            // 已完成状态的取消逻辑
            System.out.println("订单已完成,无法取消");
        } else if ("CANCELLED".equals(state)) {
            // 已取消状态的取消逻辑
            System.out.println("订单已是取消状态");
        }
    }
    
    // 每新增一个操作,就要重复一遍if-else地狱
}

这种写法的痛点

  • 条件判断爆炸:大量的if-else或switch-case语句
  • 违反开闭原则:新增状态需要修改所有相关方法
  • 代码臃肿:同一个方法包含所有状态的处理逻辑
  • 难以维护:状态转换逻辑分散在各个方法中
  • 容易出错:状态转换关系不清晰,容易遗漏

2. 状态模式:本质与定义

2.1 模式定义

状态模式(State Pattern):允许一个对象在其内部状态改变时改变它的行为,使对象看起来似乎修改了它的类。

2.2 模式结构

java 复制代码
// 状态接口
public interface State {
    void handle(Context context);
}

// 具体状态类
public class ConcreteStateA implements State {
    @Override
    public void handle(Context context) {
        System.out.println("处理状态A的逻辑");
        // 状态转换
        context.setState(new ConcreteStateB());
    }
}

public class ConcreteStateB implements State {
    @Override
    public void handle(Context context) {
        System.out.println("处理状态B的逻辑");
        // 状态转换
        context.setState(new ConcreteStateA());
    }
}

// 上下文类
public class Context {
    private State currentState;
    
    public Context(State initialState) {
        this.currentState = initialState;
    }
    
    public void setState(State state) {
        this.currentState = state;
        System.out.println("状态已转换为: " + state.getClass().getSimpleName());
    }
    
    public void request() {
        currentState.handle(this);
    }
    
    public State getCurrentState() {
        return currentState;
    }
}

3. 深入理解:状态模式的三重境界

3.1 第一重:行为与状态的绑定

核心思想:将每个状态的行为封装在独立的类中。

java 复制代码
// 不好的做法:一个类包含所有状态的行为
public class BadOrder {
    public void process() {
        if (state == PENDING) { /* 逻辑A */ }
        else if (state == PAID) { /* 逻辑B */ }
        // ...
    }
}

// 好的做法:每个状态一个类
public interface OrderState {
    void process(Order order);
    void cancel(Order order);
}

public class PendingState implements OrderState {
    @Override
    public void process(Order order) {
        // 只关注待支付状态的处理逻辑
    }
}

3.2 第二重:状态转换的集中管理

设计原则的体现:状态转换逻辑封装在状态类内部,上下文无需关心如何转换。

java 复制代码
public class PaidState implements OrderState {
    @Override
    public void process(Order order) {
        // 处理发货逻辑
        order.ship();
        // 状态转换:当前状态决定下一个状态
        order.setState(new ShippedState());
    }
}

3.3 第三重:状态机的显式建模

通过状态模式显式地建模状态机,使状态转换关系清晰可见。

java 复制代码
// 状态机配置
public class StateMachine {
    private Map<State, Map<Event, State>> transitions = new HashMap<>();
    
    public void addTransition(State from, Event event, State to) {
        transitions.computeIfAbsent(from, k -> new HashMap<>()).put(event, to);
    }
    
    public State getNextState(State current, Event event) {
        return transitions.getOrDefault(current, Collections.emptyMap()).get(event);
    }
}

4. 实战案例:完整的电商订单状态系统

让我们来看一个完整的例子:

java 复制代码
// 订单状态接口
public interface OrderState {
    void process(Order order);
    void cancel(Order order);
    void pay(Order order);
    void ship(Order order);
    void deliver(Order order);
    void complete(Order order);
    String getName();
}

// 具体状态类
@Slf4j
public class PendingPaymentState implements OrderState {
    @Override
    public void process(Order order) {
        log.info("订单待支付,请先完成支付");
    }
    
    @Override
    public void cancel(Order order) {
        log.info("取消待支付订单");
        order.setState(new CancelledState());
        order.addLog("用户取消订单");
    }
    
    @Override
    public void pay(Order order) {
        log.info("处理订单支付");
        // 支付处理逻辑
        boolean paymentSuccess = processPayment(order);
        if (paymentSuccess) {
            order.setState(new PaidState());
            order.addLog("支付成功");
        } else {
            log.warn("支付失败,订单保持待支付状态");
            order.addLog("支付失败");
        }
    }
    
    @Override
    public void ship(Order order) {
        log.warn("订单未支付,无法发货");
    }
    
    @Override
    public void deliver(Order order) {
        log.warn("订单未支付,无法收货");
    }
    
    @Override
    public void complete(Order order) {
        log.warn("订单未支付,无法完成");
    }
    
    @Override
    public String getName() {
        return "PENDING_PAYMENT";
    }
    
    private boolean processPayment(Order order) {
        // 模拟支付处理
        log.info("调用支付网关处理支付...");
        return true; // 假设支付成功
    }
}

@Slf4j
public class PaidState implements OrderState {
    @Override
    public void process(Order order) {
        log.info("订单已支付,准备发货");
    }
    
    @Override
    public void cancel(Order order) {
        log.info("取消已支付订单,处理退款");
        // 退款逻辑
        processRefund(order);
        order.setState(new CancelledState());
        order.addLog("取消订单,退款处理中");
    }
    
    @Override
    public void pay(Order order) {
        log.warn("订单已支付,无需重复支付");
    }
    
    @Override
    public void ship(Order order) {
        log.info("订单发货处理");
        // 发货逻辑
        boolean shipSuccess = processShipping(order);
        if (shipSuccess) {
            order.setState(new ShippedState());
            order.addLog("订单已发货");
        }
    }
    
    @Override
    public void deliver(Order order) {
        log.warn("订单未发货,无法确认收货");
    }
    
    @Override
    public void complete(Order order) {
        log.warn("订单未完成配送,无法完成");
    }
    
    @Override
    public String getName() {
        return "PAID";
    }
    
    private boolean processShipping(Order order) {
        log.info("生成发货单,通知仓库发货...");
        return true;
    }
    
    private void processRefund(Order order) {
        log.info("调用支付网关处理退款...");
    }
}

@Slf4j
public class ShippedState implements OrderState {
    @Override
    public void process(Order order) {
        log.info("订单已发货,等待确认收货");
    }
    
    @Override
    public void cancel(Order order) {
        log.warn("订单已发货,无法取消");
    }
    
    @Override
    public void pay(Order order) {
        log.warn("订单已支付,无需重复支付");
    }
    
    @Override
    public void ship(Order order) {
        log.warn("订单已发货,无需重复发货");
    }
    
    @Override
    public void deliver(Order order) {
        log.info("确认订单收货");
        order.setState(new DeliveredState());
        order.addLog("用户确认收货");
    }
    
    @Override
    public void complete(Order order) {
        log.warn("订单未收货,无法完成");
    }
    
    @Override
    public String getName() {
        return "SHIPPED";
    }
}

@Slf4j
public class DeliveredState implements OrderState {
    @Override
    public void process(Order order) {
        log.info("订单已送达,等待用户确认完成");
    }
    
    @Override
    public void cancel(Order order) {
        log.warn("订单已送达,无法取消");
    }
    
    @Override
    public void pay(Order order) {
        log.warn("订单已完成支付,无需重复支付");
    }
    
    @Override
    public void ship(Order order) {
        log.warn("订单已发货,无需重复发货");
    }
    
    @Override
    public void deliver(Order order) {
        log.warn("订单已收货,无需重复确认");
    }
    
    @Override
    public void complete(Order order) {
        log.info("完成订单");
        order.setState(new CompletedState());
        order.addLog("订单完成");
    }
    
    @Override
    public String getName() {
        return "DELIVERED";
    }
}

@Slf4j
public class CompletedState implements OrderState {
    @Override
    public void process(Order order) {
        log.info("订单已完成,感谢购买");
    }
    
    @Override
    public void cancel(Order order) {
        log.warn("订单已完成,无法取消");
    }
    
    @Override
    public void pay(Order order) {
        log.warn("订单已完成支付,无需重复支付");
    }
    
    @Override
    public void ship(Order order) {
        log.warn("订单已完成发货,无需重复发货");
    }
    
    @Override
    public void deliver(Order order) {
        log.warn("订单已完成收货,无需重复确认");
    }
    
    @Override
    public void complete(Order order) {
        log.warn("订单已完成,无需重复完成");
    }
    
    @Override
    public String getName() {
        return "COMPLETED";
    }
}

@Slf4j
public class CancelledState implements OrderState {
    @Override
    public void process(Order order) {
        log.warn("订单已取消,无法处理");
    }
    
    @Override
    public void cancel(Order order) {
        log.warn("订单已是取消状态");
    }
    
    @Override
    public void pay(Order order) {
        log.warn("订单已取消,无法支付");
    }
    
    @Override
    public void ship(Order order) {
        log.warn("订单已取消,无法发货");
    }
    
    @Override
    public void deliver(Order order) {
        log.warn("订单已取消,无法收货");
    }
    
    @Override
    public void complete(Order order) {
        log.warn("订单已取消,无法完成");
    }
    
    @Override
    public String getName() {
        return "CANCELLED";
    }
}

// 订单类 - 上下文
@Slf4j
public class Order {
    private String orderId;
    private OrderState state;
    private List<String> logs = new ArrayList<>();
    private LocalDateTime createTime;
    private BigDecimal amount;
    
    public Order(String orderId, BigDecimal amount) {
        this.orderId = orderId;
        this.amount = amount;
        this.state = new PendingPaymentState();
        this.createTime = LocalDateTime.now();
        this.logs.add("订单创建");
        log.info("创建新订单: {},金额: {},初始状态: {}", orderId, amount, state.getName());
    }
    
    // 委托给当前状态对象
    public void process() {
        log.info("处理订单: {}", orderId);
        state.process(this);
    }
    
    public void cancel() {
        log.info("取消订单: {}", orderId);
        state.cancel(this);
    }
    
    public void pay() {
        log.info("支付订单: {}", orderId);
        state.pay(this);
    }
    
    public void ship() {
        log.info("发货订单: {}", orderId);
        state.ship(this);
    }
    
    public void deliver() {
        log.info("确认收货订单: {}", orderId);
        state.deliver(this);
    }
    
    public void complete() {
        log.info("完成订单: {}", orderId);
        state.complete(this);
    }
    
    // 状态管理
    public void setState(OrderState state) {
        this.state = state;
        log.debug("订单 {} 状态变更为: {}", orderId, state.getName());
    }
    
    public String getCurrentState() {
        return state.getName();
    }
    
    public void addLog(String message) {
        String logEntry = String.format("[%s] %s", 
            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), 
            message);
        logs.add(logEntry);
    }
    
    public void printStatus() {
        System.out.println("=== 订单状态 ===");
        System.out.println("订单号: " + orderId);
        System.out.println("当前状态: " + getCurrentState());
        System.out.println("创建时间: " + createTime);
        System.out.println("订单金额: " + amount);
        System.out.println("操作日志:");
        logs.forEach(log -> System.out.println("  " + log));
        System.out.println("==============");
    }
    
    // getters
    public String getOrderId() { return orderId; }
    public BigDecimal getAmount() { return amount; }
    public List<String> getLogs() { return new ArrayList<>(logs); }
}

// 使用示例
@Slf4j
public class OrderStateDemo {
    public static void main(String[] args) {
        // 创建订单
        Order order = new Order("ORDER_001", new BigDecimal("199.99"));
        order.printStatus();
        
        // 正常流程
        order.pay();        // 支付
        order.ship();       // 发货
        order.deliver();    // 收货
        order.complete();   // 完成
        
        order.printStatus();
        
        // 创建另一个订单测试取消流程
        Order order2 = new Order("ORDER_002", new BigDecimal("99.50"));
        order2.cancel();    // 取消
        
        order2.printStatus();
        
        // 测试非法操作
        order2.pay();       // 已取消的订单尝试支付
    }
}

5. Spring Boot中的优雅实现

在Spring Boot中,我们可以利用状态机框架和依赖注入让状态模式更加优雅:

java 复制代码
// 状态枚举
public enum OrderStatus {
    PENDING_PAYMENT,
    PAID,
    SHIPPED,
    DELIVERED,
    COMPLETED,
    CANCELLED
}

// 事件枚举
public enum OrderEvent {
    PAY,
    CANCEL,
    SHIP,
    DELIVER,
    COMPLETE
}

// 状态机配置
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderStatus, OrderEvent> {
    
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderEvent> states)
            throws Exception {
        states
            .withStates()
                .initial(OrderStatus.PENDING_PAYMENT)
                .states(EnumSet.allOf(OrderStatus.class))
                .end(OrderStatus.COMPLETED)
                .end(OrderStatus.CANCELLED);
    }
    
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderEvent> transitions)
            throws Exception {
        transitions
            .withExternal()
                .source(OrderStatus.PENDING_PAYMENT).target(OrderStatus.PAID)
                .event(OrderEvent.PAY)
                .and()
            .withExternal()
                .source(OrderStatus.PENDING_PAYMENT).target(OrderStatus.CANCELLED)
                .event(OrderEvent.CANCEL)
                .and()
            .withExternal()
                .source(OrderStatus.PAID).target(OrderStatus.SHIPPED)
                .event(OrderEvent.SHIP)
                .and()
            .withExternal()
                .source(OrderStatus.PAID).target(OrderStatus.CANCELLED)
                .event(OrderEvent.CANCEL)
                .and()
            .withExternal()
                .source(OrderStatus.SHIPPED).target(OrderStatus.DELIVERED)
                .event(OrderEvent.DELIVER)
                .and()
            .withExternal()
                .source(OrderStatus.DELIVERED).target(OrderStatus.COMPLETED)
                .event(OrderEvent.COMPLETE);
    }
}

// 订单实体
@Entity
@Table(name = "orders")
@Data
public class Order {
    @Id
    private String id;
    
    private BigDecimal amount;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    @CreationTimestamp
    private LocalDateTime createTime;
    
    @UpdateTimestamp
    private LocalDateTime updateTime;
    
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderLog> logs = new ArrayList<>();
    
    // 状态机不持久化
    @Transient
    private StateMachine<OrderStatus, OrderEvent> stateMachine;
}

// 订单日志
@Entity
@Table(name = "order_logs")
@Data
public class OrderLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "order_id")
    private Order order;
    
    private String message;
    
    @CreationTimestamp
    private LocalDateTime createTime;
}

// 订单服务
@Service
@Transactional
@Slf4j
public class OrderService {
    private final OrderRepository orderRepository;
    private final StateMachineFactory<OrderStatus, OrderEvent> stateMachineFactory;
    private final OrderLogRepository logRepository;
    
    public OrderService(OrderRepository orderRepository,
                       StateMachineFactory<OrderStatus, OrderEvent> stateMachineFactory,
                       OrderLogRepository logRepository) {
        this.orderRepository = orderRepository;
        this.stateMachineFactory = stateMachineFactory;
        this.logRepository = logRepository;
    }
    
    public Order createOrder(BigDecimal amount) {
        Order order = new Order();
        order.setId("ORDER_" + System.currentTimeMillis());
        order.setAmount(amount);
        order.setStatus(OrderStatus.PENDING_PAYMENT);
        
        order = orderRepository.save(order);
        addLog(order, "订单创建");
        
        log.info("创建订单: {},金额: {}", order.getId(), amount);
        return order;
    }
    
    public Order processEvent(String orderId, OrderEvent event) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
        
        StateMachine<OrderStatus, OrderEvent> stateMachine = buildStateMachine(order);
        
        // 发送事件
        boolean accepted = stateMachine.sendEvent(event);
        
        if (accepted) {
            // 更新订单状态
            OrderStatus newStatus = stateMachine.getState().getId();
            order.setStatus(newStatus);
            order = orderRepository.save(order);
            
            addLog(order, "执行操作: " + event + ",状态变更为: " + newStatus);
            log.info("订单 {} 执行操作 {},新状态: {}", orderId, event, newStatus);
        } else {
            log.warn("订单 {} 无法执行操作 {},当前状态: {}", orderId, event, order.getStatus());
            throw new IllegalStateException("无法执行操作: " + event + ",当前状态: " + order.getStatus());
        }
        
        return order;
    }
    
    public boolean canProcessEvent(String orderId, OrderEvent event) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
        
        StateMachine<OrderStatus, OrderEvent> stateMachine = buildStateMachine(order);
        return stateMachine.sendEvent(event);
    }
    
    public List<OrderEvent> getAvailableEvents(String orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
        
        StateMachine<OrderStatus, OrderEvent> stateMachine = buildStateMachine(order);
        return stateMachine.getTransitions().stream()
                .filter(transition -> transition.getSource().getId() == order.getStatus())
                .map(transition -> transition.getTrigger().getEvent())
                .collect(Collectors.toList());
    }
    
    private StateMachine<OrderStatus, OrderEvent> buildStateMachine(Order order) {
        StateMachine<OrderStatus, OrderEvent> stateMachine = stateMachineFactory.getStateMachine();
        stateMachine.start();
        stateMachine.getStateMachineAccessor().doWithAllRegions(access -> {
            access.resetStateMachine(new DefaultStateMachineContext<>(order.getStatus(), null, null, null));
        });
        return stateMachine;
    }
    
    private void addLog(Order order, String message) {
        OrderLog log = new OrderLog();
        log.setOrder(order);
        log.setMessage(message);
        logRepository.save(log);
    }
}

// REST控制器
@RestController
@RequestMapping("/api/orders")
@Slf4j
public class OrderController {
    private final OrderService orderService;
    
    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
    
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
        Order order = orderService.createOrder(request.getAmount());
        return ResponseEntity.ok(order);
    }
    
    @PostMapping("/{orderId}/events/{event}")
    public ResponseEntity<Order> processEvent(@PathVariable String orderId,
                                             @PathVariable OrderEvent event) {
        try {
            Order order = orderService.processEvent(orderId, event);
            return ResponseEntity.ok(order);
        } catch (IllegalStateException e) {
            return ResponseEntity.badRequest().build();
        }
    }
    
    @GetMapping("/{orderId}/available-events")
    public ResponseEntity<List<OrderEvent>> getAvailableEvents(@PathVariable String orderId) {
        List<OrderEvent> events = orderService.getAvailableEvents(orderId);
        return ResponseEntity.ok(events);
    }
    
    @GetMapping("/{orderId}/can-process/{event}")
    public ResponseEntity<Boolean> canProcessEvent(@PathVariable String orderId,
                                                  @PathVariable OrderEvent event) {
        boolean canProcess = orderService.canProcessEvent(orderId, event);
        return ResponseEntity.ok(canProcess);
    }
}

6. 状态模式的变体与进阶用法

6.1 状态模式 + 策略模式

结合策略模式实现更灵活的状态行为:

java 复制代码
// 状态行为策略
public interface StateBehavior {
    void onEnter();
    void onExit();
    boolean canTransitionTo(State nextState);
}

// 带行为的订单状态
public abstract class BehaviorOrderState implements OrderState {
    protected StateBehavior behavior;
    
    public BehaviorOrderState(StateBehavior behavior) {
        this.behavior = behavior;
        this.behavior.onEnter();
    }
    
    @Override
    public void process(Order order) {
        // 默认实现
    }
    
    public void transitionTo(Order order, OrderState nextState) {
        if (behavior.canTransitionTo((State) nextState)) {
            behavior.onExit();
            order.setState(nextState);
        } else {
            throw new IllegalStateException("无法转换到目标状态");
        }
    }
}

6.2 有限状态机(FSM)实现

java 复制代码
// 状态机
@Slf4j
public class StateMachine<S, E> {
    private S currentState;
    private final Map<S, Map<E, S>> transitions = new HashMap<>();
    private final Map<S, Runnable> onEnterCallbacks = new HashMap<>();
    private final Map<S, Runnable> onExitCallbacks = new HashMap<>();
    
    public StateMachine(S initialState) {
        this.currentState = initialState;
        onEnterCallbacks.getOrDefault(initialState, () -> {}).run();
    }
    
    public void addTransition(S from, E event, S to) {
        transitions.computeIfAbsent(from, k -> new HashMap<>()).put(event, to);
    }
    
    public void onEnter(S state, Runnable callback) {
        onEnterCallbacks.put(state, callback);
    }
    
    public void onExit(S state, Runnable callback) {
        onExitCallbacks.put(state, callback);
    }
    
    public boolean sendEvent(E event) {
        Map<E, S> stateTransitions = transitions.get(currentState);
        if (stateTransitions != null && stateTransitions.containsKey(event)) {
            S nextState = stateTransitions.get(event);
            
            // 执行退出回调
            onExitCallbacks.getOrDefault(currentState, () -> {}).run();
            
            // 转换状态
            currentState = nextState;
            log.info("状态转换: {} -> {}", currentState, nextState);
            
            // 执行进入回调
            onEnterCallbacks.getOrDefault(nextState, () -> {}).run();
            
            return true;
        }
        return false;
    }
    
    public S getCurrentState() {
        return currentState;
    }
    
    public List<E> getAvailableEvents() {
        Map<E, S> stateTransitions = transitions.get(currentState);
        return stateTransitions != null ? new ArrayList<>(stateTransitions.keySet()) : Collections.emptyList();
    }
}

7. 状态模式 vs 其他模式

7.1 状态模式 vs 策略模式

  • 策略模式:客户端主动选择策略,策略之间相互独立
  • 状态模式:状态自动转换,状态之间有关联关系

7.2 状态模式 vs 状态机模式

  • 状态模式:设计模式,关注对象行为随状态变化
  • 状态机模式:架构模式,关注状态转换的建模和管理

7.3 状态模式 vs 条件判断

  • 条件判断:简单的if-else,适合状态少、逻辑简单
  • 状态模式:状态多、转换复杂,需要更好的扩展性

8. 总结与思考

8.1 状态模式的优点

  1. 单一职责原则:每个状态一个类,职责清晰
  2. 开闭原则:新增状态无需修改现有代码
  3. 消除条件判断:用多态代替复杂的条件判断
  4. 状态转换明确:状态转换逻辑集中管理
  5. 易于测试:每个状态可以独立测试

8.2 状态模式的缺点

  1. 类数量增加:每个状态一个类,可能产生很多小类
  2. 复杂度增加:简单的状态机可能过度设计
  3. 状态共享困难:状态之间共享数据比较麻烦
  4. 学习成本:理解双分派和状态转换需要时间

8.3 深入思考

状态模式的本质是**"行为的状态化"**。它将对象的行为按照状态进行划分,让每个状态专注于自己的职责,通过状态转换来实现完整的行为流程。

设计之美的思考

"状态模式教会我们用'分治'的思想来管理复杂的状态逻辑。就像现实世界中的工作流程一样,每个阶段都有明确的职责和边界,阶段之间的转换也有清晰的规则。这种结构化的思维方式让我们的代码更加清晰和健壮。"

从源码的角度看,状态模式在Java中有着广泛应用:

  • Java线程的状态管理
  • Servlet的生命周期管理
  • Spring状态机框架
  • 工作流引擎的实现
  • 游戏开发中的角色状态管理

何时使用状态模式

  • 对象的行为取决于它的状态,并且必须在运行时根据状态改变行为
  • 操作中有大量的条件语句,这些条件依赖于对象的状态
  • 状态转换逻辑复杂,需要清晰的管理
  • 需要容易地添加新的状态和转换

使用场景

  • 订单和工作流系统
  • 游戏角色和NPC行为
  • UI组件的状态管理
  • 网络协议的状态处理
  • 硬件设备的控制逻辑

下一篇预告:设计模式手册020 - 模板方法 - 定义算法骨架的艺术


版权声明:本文为CSDN博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

相关推荐
guslegend7 小时前
SpringSecurity认证原理与实战
java
JIngJaneIL7 小时前
基于java+ vue畅游游戏销售管理系统(源码+数据库+文档)
java·开发语言·数据库·vue.js·spring boot·游戏
while(1){yan}7 小时前
HTTP的加密过程
java·开发语言·网络·网络协议·http·青少年编程
小坏讲微服务7 小时前
Spring Boot4.0 集成 Redis 实现看门狗 Lua 脚本分布式锁完整使用
java·spring boot·redis·分布式·后端·lua
一念一花一世界8 小时前
Arbess从基础到实践(20) - 集成GitHub+SonarQube实现Java项目自动化部署
java·github·cicd·arbess
syt_10138 小时前
设计模式之-发布订阅者模式
设计模式
艾莉丝努力练剑8 小时前
【Python库和代码案例:第一课】Python 标准库与第三方库实战指南:从日期处理到 Excel 操作
java·服务器·开发语言·人工智能·python·pycharm·pip
Yu_Lijing8 小时前
基于C++的《Head First设计模式》笔记——策略模式
c++·笔记·设计模式
YDS8298 小时前
SpringCloud —— 配置管理
java·spring·spring cloud