状态模式

简介

允许对象在内部状态改变时改变它的行为。

使用场景:

  • 订单状态流转

  • TCP连接状态

  • 游戏角色状态

  • 工作流引擎

实现要点:

  • 状态接口定义行为

  • 具体状态类实现不同行为

  • 上下文持有当前状态

UML

代码示例

  1. 订单实体类

@Data
public class Order {
    private String orderId;
    private String customerName;
    private String userId;
    private String productId;
    private String productName;
    private double amount;
    private OrderStatusEnum status;
    private Map<String, Object> orderData;
    private long createdAt;
    private long updatedAt;
    
    // 构造函数
    public Order() {
        this.orderData = new HashMap<>();
    }
    
    public Order(String orderId, String customerName, String userId, String productId, 
                String productName, double amount, OrderStatusEnum status) {
        this();
        this.orderId = orderId;
        this.customerName = customerName;
        this.userId = userId;
        this.productId = productId;
        this.productName = productName;
        this.amount = amount;
        this.status = status;
        this.createdAt = System.currentTimeMillis();
        this.updatedAt = System.currentTimeMillis();
    }
    
    // 业务方法
    public void updateStatus(OrderStatusEnum newStatus) {
        this.status = newStatus;
        this.updatedAt = System.currentTimeMillis();
    }
    
    public void addOrderData(String key, Object value) {
        if (this.orderData == null) {
            this.orderData = new HashMap<>();
        }
        this.orderData.put(key, value);
    }
    
    public Object getOrderData(String key) {
        return this.orderData != null ? this.orderData.get(key) : null;
    }
}
  1. 订单状态

public enum OrderStatusEnum {
    PENDING_PAYMENT("PENDING_PAYMENT", "待支付"),
    PAID("PAID", "已支付"),
    SHIPPED("SHIPPED", "已发货"),
    COMPLETED("COMPLETED", "已完成"),
    CANCELLED("CANCELLED", "已取消"),
    REFUNDING("REFUNDING", "退款中");

    private final String code;
    private final String name;

    OrderStatusEnum(String code, String name) {
        this.code = code;
        this.name = name;
    }

    public String getCode() { 
        return code; 
    }
    
    public String getName() { 
        return name; 
    }
}
  1. 订单状态接口

public interface OrderState {
    void pay(OrderContext context);
    void deliver(OrderContext context);
    void cancel(OrderContext context);
    void complete(OrderContext context);
    OrderStatusEnum getStatus();
}
  1. 具体的状态

/**
 * @author dcx
 * @description 待支付状态
 * @create 2025-01-27
 */
public class PendingPaymentState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("处理支付...");
        if (Math.random() > 0.3) {
            System.out.println("支付成功!");
            context.changeState(OrderStatusEnum.PAID);
        } else {
            System.out.println("支付失败!");
            context.changeState(OrderStatusEnum.CANCELLED);
        }
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单尚未支付,无法发货!");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("取消订单...");
        context.changeState(OrderStatusEnum.CANCELLED);
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("订单尚未支付,无法完成!");
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.PENDING_PAYMENT;
    }
}
/**
 * @author dcx
 * @description 已支付状态
 * @create 2025-01-27
 */
public class PaidState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单已支付,无需重复支付!");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("开始发货...");
        context.getOrderData().put("deliveryTime", System.currentTimeMillis());
        context.getOrderData().put("trackingNumber", "TRK" + System.currentTimeMillis());
        context.changeState(OrderStatusEnum.SHIPPED);
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已支付,需要退款处理...");
        context.changeState(OrderStatusEnum.REFUNDING);
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("订单尚未发货,无法完成!");
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.PAID;
    }
}
/**
 * @author dcx
 * @description 已取消状态
 * @create 2025-01-27
 */
public class CancelledState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单已取消,无法支付!");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单已取消,无法发货!");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已取消!");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("订单已取消,无法完成!");
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.CANCELLED;
    }
}
/**
 * @author dcx
 * @description 已发货状态
 * @create 2025-01-27
 */
public class ShippedState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单已支付!");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单已发货!");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已发货,无法取消!");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("确认收货...");
        context.getOrderData().put("completedTime", System.currentTimeMillis());
        context.changeState(OrderStatusEnum.COMPLETED);
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.SHIPPED;
    }
}
/**
 * @author dcx
 * @description 退款中状态
 * @create 2025-01-27
 */
public class RefundingState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单退款中,无法支付!");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单退款中,无法发货!");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单退款中!");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("退款处理完成...");
        context.changeState(OrderStatusEnum.CANCELLED);
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.REFUNDING;
    }
}
/**
 * @author dcx
 * @description 已完成状态
 * @create 2025-01-27
 */
public class CompletedState implements OrderState {
    
    @Override
    public void pay(OrderContext context) {
        System.out.println("订单已完成!");
    }

    @Override
    public void deliver(OrderContext context) {
        System.out.println("订单已完成!");
    }

    @Override
    public void cancel(OrderContext context) {
        System.out.println("订单已完成,无法取消!");
    }

    @Override
    public void complete(OrderContext context) {
        System.out.println("订单已完成!");
    }

    @Override
    public OrderStatusEnum getStatus() {
        return OrderStatusEnum.COMPLETED;
    }
}
  1. 订单状态工厂

public class OrderStateFactory {
    
    public static OrderState createState(OrderStatusEnum status) {
        switch (status) {
            case PENDING_PAYMENT:
                return new PendingPaymentState();
            case PAID:
                return new PaidState();
            case SHIPPED:
                return new ShippedState();
            case COMPLETED:
                return new CompletedState();
            case CANCELLED:
                return new CancelledState();
            case REFUNDING:
                return new RefundingState();
            default:
                throw new IllegalArgumentException("未知状态: " + status);
        }
    }
}
  1. 订单上下文

public class OrderContext {
    private OrderState currentState;
    private Order order; // 使用Order类封装订单信息

    // 构造函数 - 使用Order对象
    public OrderContext(Order order) {
        this.order = order;
        // 根据订单状态初始化当前状态对象
        this.currentState = OrderStateFactory.createState(order.getStatus());
    }

    // 状态转换方法
    public void changeState(OrderStatusEnum newStatus) {
        System.out.println("订单 " + order.getOrderId() + " 状态从 " + 
            order.getStatus().getName() + " 转换为 " + newStatus.getName());
        
        // 更新订单状态
        order.updateStatus(newStatus);
        this.currentState = OrderStateFactory.createState(newStatus);
        
        // 保存到数据库
        saveToDatabase();
    }

    // 委托给当前状态处理的方法
    public void pay() {
        currentState.pay(this);
    }

    public void deliver() {
        currentState.deliver(this);
    }

    public void cancel() {
        currentState.cancel(this);
    }

    public void complete() {
        currentState.complete(this);
    }

    // 模拟保存到数据库
    private void saveToDatabase() {
        System.out.println("保存订单状态到数据库: " + order.getOrderId() + " -> " + order.getStatus().getName());
        // 这里应该是实际的数据库保存逻辑
        // orderRepository.updateStatus(order.getOrderId(), order.getStatus().getCode(), order.getUpdatedAt());
    }

    // Getter方法
    public OrderState getCurrentState() { return currentState; }
    public Order getOrder() { return order; }
    
    // 便捷方法,委托给Order对象
    public String getOrderId() { return order.getOrderId(); }
    public String getCustomerName() { return order.getCustomerName(); }
    public double getAmount() { return order.getAmount(); }
    public OrderStatusEnum getStatus() { return order.getStatus(); }
    public java.util.Map<String, Object> getOrderData() { return order.getOrderData(); }
    public long getCreatedAt() { return order.getCreatedAt(); }
    public long getUpdatedAt() { return order.getUpdatedAt(); }

    @Override
    public String toString() {
        return "OrderContext{" +
                "order=" + order +
                ", currentState=" + currentState.getClass().getSimpleName() +
                '}';
    }
}
  1. 订单服务

public class OrderService {
    
    /**
     * 从数据库加载订单
     */
    public OrderContext loadOrderFromDatabase(String orderId) {
        System.out.println("从数据库加载订单: " + orderId);
        
        // 创建Order对象
        Order order = new Order(
            orderId,
            "张三",
            "USER001",
            "PROD001",
            "iPhone 15",
            299.99,
            OrderStatusEnum.PENDING_PAYMENT
        );
        
        // 设置订单数据
        order.addOrderData("paymentMethod", "支付宝");
        order.addOrderData("address", "北京市朝阳区");
        order.addOrderData("phone", "13800138000");
        
        // 设置时间
        order.setCreatedAt(System.currentTimeMillis() - 86400000); // 1天前创建
        order.setUpdatedAt(System.currentTimeMillis() - 3600000);  // 1小时前更新
        
        return new OrderContext(order);
    }
    
    /**
     * 批量加载订单
     */
    public List<OrderContext> loadOrdersByStatus(OrderStatusEnum status) {
        System.out.println("从数据库加载状态为 " + status.getName() + " 的订单");
        
        List<OrderContext> orders = new ArrayList<>();
        // 模拟查询结果
        for (int i = 1; i <= 3; i++) {
            String orderId = "ORD" + String.format("%03d", i);
            orders.add(loadOrderFromDatabase(orderId));
        }
        return orders;
    }
    
    /**
     * 创建新订单
     */
    public OrderContext createOrder(String customerName, String userId, String productId, 
                                  String productName, double amount) {
        String orderId = "ORD" + System.currentTimeMillis();
        
        Order order = new Order(
            orderId,
            customerName,
            userId,
            productId,
            productName,
            amount,
            OrderStatusEnum.PENDING_PAYMENT
        );
        
        return new OrderContext(order);
    }
}
  1. 使用方式

public class OrderStatePatternTest {

    /**
     * 测试方法
     */
    public static void main(String[] args) {
        System.out.println("=== 使用Order类的状态模式演示 ===\n");

        OrderService orderService = new OrderService();

        // 1. 从数据库加载一个待支付的订单
        System.out.println("=== 加载待支付订单 ===");
        OrderContext order = orderService.loadOrderFromDatabase("ORD001");
        System.out.println("加载的订单:" + order);
        System.out.println("订单详情:" + order.getOrder());
        System.out.println();

        // 2. 继续处理这个订单
        System.out.println("=== 继续处理订单 ===");
        order.pay();        // 支付
        order.deliver();    // 发货
        order.complete();   // 完成
        System.out.println();

        // 3. 创建一个新订单
        System.out.println("=== 创建新订单 ===");
        OrderContext newOrder = orderService.createOrder(
                "李四",
                "USER002",
                "PROD002",
                "MacBook Pro",
                12999.99
        );
        System.out.println("新订单:" + newOrder);
        System.out.println("订单详情:" + newOrder.getOrder());

        // 处理新订单
        newOrder.pay();
        newOrder.deliver();
        newOrder.complete();
        System.out.println();

        // 4. 手动创建一个已支付的订单
        System.out.println("=== 手动创建已支付订单 ===");
        Order paidOrder = new Order(
                "ORD003",
                "王五",
                "USER003",
                "PROD003",
                "iPad Air",
                4999.99,
                OrderStatusEnum.PAID
        );
        paidOrder.addOrderData("paymentMethod", "微信支付");
        paidOrder.addOrderData("address", "上海市浦东新区");
        paidOrder.setCreatedAt(System.currentTimeMillis() - 7200000);  // 2小时前创建
        paidOrder.setUpdatedAt(System.currentTimeMillis() - 1800000);   // 30分钟前更新

        OrderContext paidOrderContext = new OrderContext(paidOrder);
        System.out.println("已支付订单:" + paidOrderContext);

        // 继续处理
        paidOrderContext.deliver();    // 发货
        paidOrderContext.complete();   // 完成
        System.out.println();

        // 5. 批量处理待支付订单
        System.out.println("=== 批量处理待支付订单 ===");
        java.util.List<OrderContext> pendingOrders = orderService.loadOrdersByStatus(OrderStatusEnum.PENDING_PAYMENT);
        for (OrderContext pendingOrder : pendingOrders) {
            System.out.println("处理订单:" + pendingOrder.getOrderId() +
                    " - " + pendingOrder.getOrder().getProductName());
            pendingOrder.pay();
            System.out.println();
        }

        // 6. 测试状态工厂
        System.out.println("=== 测试状态工厂 ===");
        for (OrderStatusEnum status : OrderStatusEnum.values()) {
            OrderState state = OrderStateFactory.createState(status);
            System.out.println("状态: " + status.getName() + " -> 状态对象: " + state.getClass().getSimpleName());
        }
        System.out.println();
    }
}

Last updated

Was this helpful?