设计模式-状态模式

写在前面

Hello,我是易元,这篇文章是我学习设计模式时的笔记和心得体会。如果其中有错误,欢迎大家留言指正!


需求背景

小易是一家中型电商公司的技术负责人,订单处理系统随着业务的快速发展逐渐复杂,订单状态繁杂,并且每种状态下,可执行操作也各不相同:

  • 在 "已创建" 状态下,用户可以支付订单或者取消订单。
  • 在 "已支付" 状态下,系统可以进入审核流程或者直接进入配送流程。
  • 在 "待审核" 状态下,管理员可以审核通过或拒绝订单。
  • 在 "配送中" 状态下,系统可以标记订单为已送达。
  • 在 "已完成" 状态下,用户可以申请退款或者评价订单。
  • 在 "已取消" 状态下,系统不允许任何进一步操作。

这个场景非常适合应用状态模式,原因如下:

  1. 系统中存在明确的状态及状态转换。
  2. 对象的行为取决于其当前状态。
  3. 状态转换规则复杂且可能经常变化。
  4. 需要避免大量的条件判断语句。

接下来,我们将分析这个订单处理系统的案例,首先使用传统的编码方式实现,然后识别其中的问题,最后应用状态模式进行重构。

传统方式实现

订单状态枚举常量
scss 复制代码
@Getter
@AllArgsConstructor
public enum OrderStateEnum {

    STATUS_CREATED(1, "已创建"),

    STATUS_PAID(2, "已支付"),

    STATUS_REVIEWING(3, "待审核"),

    STATUS_DELIVERING(4, "配送中"),

    STATUS_COMPLETED(5, "已完成"),

    STATUS_CANCELLED(6, "已取消"),

    ;

    /**
     * 类型
     */
    private final Integer value;

    /**
     * 类型名
     */
    private final String name;

    public static String getStateName(OrderStateEnum stateEnum) {
        OrderStateEnum[] values = OrderStateEnum.values();
        for (OrderStateEnum orderStateEnum : values) {
            if (orderStateEnum == stateEnum) {
                return stateEnum.getName();
            }
        }

        return "未知状态";
    }
}

状态枚举类:定义了订单的不同状态,比如已创建、已支付等,每个状态都有对应的值和描述。包含一个静态方法getStateName(),根据传入的枚举实例返回状态名称,如果找不到则返回"未知状态"。

订单信息类
arduino 复制代码
public class Order {

    /**
     * 当前状态
     */
    private OrderStateEnum status;

    /**
     * 订单ID
     */
    private String orderId;

    /**
     * 订单金额
     */
    private double amount;

    /**
     * 客户信息
     */
    private String customerInfo;

    public Order() {
    }

    public Order(OrderStateEnum status, String orderId, double amount, String customerInfo) {
        this.status = status;
        this.orderId = orderId;
        this.amount = amount;
        this.customerInfo = customerInfo;
    }

    public OrderStateEnum getStatus() {
        return status;
    }

    public void setStatus(OrderStateEnum status) {
        this.status = status;
    }

    public String getStatusName() {
        return OrderStateEnum.getStateName(this.status);
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public String getCustomerInfo() {
        return customerInfo;
    }

    public void setCustomerInfo(String customerInfo) {
        this.customerInfo = customerInfo;
    }
}

订单类Order:包含状态、订单ID、金额和客户信息等属性。提供了gettersetter方法,其中getStatusName方法调用了枚举类的getStateName来获取状态描述。

订单状态处理类
kotlin 复制代码
public class OrderProcessor {

    /**
     * 支付订单
     *
     * @param order 要支付的订单
     * @return 操作是否成功
     */
    public boolean payOrder(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_CREATED) {
            // 处理支付逻辑
            System.out.println("订单" + order.getOrderId() + "支付成功");
            order.setStatus(OrderStateEnum.STATUS_PAID);

            return true;
        }
        else {
            System.out.println("订单状态不正确,无法支付");
            return false;
        }
    }

    /**
     * 取消订单
     *
     * @param order 要取消的订单
     * @return 操作是否成功
     */
    public boolean cancelOrder(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_CREATED) {
            System.out.println("订单" + order.getOrderId() + "已取消");
            order.setStatus(STATUS_CANCELLED);

            return true;
        }
        else if (order.getStatus() == OrderStateEnum.STATUS_PAID || order.getStatus() == OrderStateEnum.STATUS_REVIEWING) {
            // 已支付或待审核状态下取消需要退款
            System.out.println("订单" + order.getOrderId() + "已取消,退款处理中");
            order.setStatus(STATUS_CANCELLED);

            return true;
        }
        else {
            System.out.println("订单状态不允许取消");
            return false;
        }
    }

    /**
     * 提交订单审核
     *
     * @param order 要审核的订单
     * @return 操作是否成功
     */
    public boolean submitForReview(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_PAID) {
            System.out.println("订单" + order.getOrderId() + "已提交审核");
            order.setStatus(OrderStateEnum.STATUS_REVIEWING);
            return true;
        }
        else {
            System.out.println("只有已支付的订单才能提交审核");
            return false;
        }
    }

    /**
     * 审核通过
     *
     * @param order 要审核的订单
     * @return 操作是否成功
     */
    public boolean approveOrder(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_REVIEWING) {
            System.out.println("订单" + order.getOrderId() + "审核通过,准备配送");
            order.setStatus(OrderStateEnum.STATUS_DELIVERING);
            return true;
        }
        else {
            System.out.println("只有待审核的订单才能审核通过");
            return false;
        }
    }

    /**
     * 开始配送
     *
     * @param order 要配送的订单
     * @return 操作是否成功
     */
    public boolean startDelivery(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_PAID) {
            // 无需审核的订单直接配送
            System.out.println("订单" + order.getOrderId() + "开始配送");
            order.setStatus(OrderStateEnum.STATUS_DELIVERING);
            return true;
        }
        else {
            System.out.println("只有已支付的订单才能开始配送");
            return false;
        }
    }

    /**
     * 完成订单
     *
     * @param order 要完成的订单
     * @return 操作是否成功
     */
    public boolean completeOrder(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_DELIVERING) {
            System.out.println("订单" + order.getOrderId() + "已送达,订单完成");
            order.setStatus(STATUS_COMPLETED);
            return true;
        }
        else {
            System.out.println("只有配送中的订单才能标记为完成");
            return false;
        }
    }

    /**
     * 申请退款
     *
     * @param order 要退款的订单
     * @return 操作是否成功
     */
    public boolean requestRefund(Order order) {
        if (order.getStatus() == OrderStateEnum.STATUS_COMPLETED) {
            System.out.println("订单" + order.getOrderId() + "申请退款中");

            // 退款逻辑
            return true;
        }
        else {
            System.out.println("只有已完成的订单才能申请退款");
            return false;
        }
    }

    /**
     * 获取订单在当前状态下可执行的操作
     *
     * @param order 订单
     * @return 可执行操作的描述
     */
    public String getAvailableActions(Order order) {
        StringBuilder actions = new StringBuilder("可执行操作: ");

        switch (order.getStatus()) {
            case STATUS_CREATED:
                actions.append("支付订单、取消订单");
                break;
            case STATUS_PAID:
                actions.append("提交审核、开始配送、取消订单");
                break;
            case STATUS_REVIEWING:
                actions.append("审核通过、取消订单");
                break;
            case STATUS_DELIVERING:
                actions.append("完成订单");
                break;
            case STATUS_COMPLETED:
                actions.append("申请退款、评价订单");
                break;
            case STATUS_CANCELLED:
                actions.append("无可用操作");
                break;
            default:
                actions.append("未知状态,无可用操作");
        }

        return actions.toString();
    }
}

订单处理类OrderProcessor:里面包含很多方法,每个方法对应不同的订单操作。比如payOrder方法用于支付订单,检查当前状态是否为已创建,如果是则更新状态为已支付。cancelOrder方法处理取消订单,根据不同状态有不同的处理逻辑,比如已支付或待审核时需要退款。submitForReview 用于提交审核,要求订单必须已支付。approveOrder审核通过后进入配送状态。startDelivery允许已支付或待审核的订单开始配送。completeOrder将配送中的订单标记为完成。requestRefund只能在完成状态申请退款。getAvailableActions返回当前状态下可执行的操作列表。

测试类
scss 复制代码
@Test
public void test_order() {
    Order order = new Order(STATUS_CREATED, "ORD-20250526-001", 299.99, "张三,13800138000,天津市南开区");

    OrderProcessor processor = new OrderProcessor();

    // 显示订单初始状态
    System.out.println("订单创建成功,当前状态: " + order.getStatusName());
    System.out.println(processor.getAvailableActions(order));
    System.out.println();

    // 支付订单
    processor.payOrder(order);
    System.out.println("当前状态: " + order.getStatusName());
    System.out.println(processor.getAvailableActions(order));
    System.out.println();

    // 提交审核
    processor.submitForReview(order);
    System.out.println("当前状态: " + order.getStatusName());
    System.out.println(processor.getAvailableActions(order));
    System.out.println();

    // 审核通过
    processor.approveOrder(order);
    System.out.println("当前状态: " + order.getStatusName());
    System.out.println(processor.getAvailableActions(order));
    System.out.println();

    // 完成订单
    processor.completeOrder(order);
    System.out.println("当前状态: " + order.getStatusName());
    System.out.println(processor.getAvailableActions(order));
    System.out.println();

    // 尝试取消已完成的订单
    boolean result = processor.cancelOrder(order);
    System.out.println("取消订单操作结果: " + (result ? "成功" : "失败"));
    System.out.println("当前状态: " + order.getStatusName());
}

测试类中,首先创建了一个订单,然后依次执行 订单支付、订单审核提交、审核通过、订单完成操作,每执行一步打印订单的状态和可执行操作,最后,尝试取消一个已完成状态下的订单,该操作将会失败,因为已完成的订单不能被取消。

运行结果
makefile 复制代码
订单创建成功,当前状态: 已创建
可执行操作: 支付订单、取消订单

订单ORD-20250526-001支付成功
当前状态: 已支付
可执行操作: 提交审核、开始配送、取消订单

订单ORD-20250526-001已提交审核
当前状态: 待审核
可执行操作: 审核通过、取消订单

订单ORD-20250526-001审核通过,准备配送
当前状态: 配送中
可执行操作: 完成订单

订单ORD-20250526-001已送达,订单完成
当前状态: 已完成
可执行操作: 申请退款、评价订单

订单状态不允许取消
取消订单操作结果: 失败
当前状态: 已完成

Process finished with exit code 0

传统实现的问题分析

条件语句过多,代码复杂度高

观察 OrderProcessor 类中的每个方法,可以发现几乎每个方法都包含有大量的条件判断语句来处理不同的状态,大量的判断使得代码难以阅读,随着状态和操作的增加,条件判断会呈现指数级增加,使得复杂度急剧上升。

状态模式

什么是状态模式

状态模式:行为型设计模式,允许对象在内部状态改变时改变其行为。模式中,将状态相关的行为抽象为独立的状态类。

核心思想:将对象的每个状态封装成独立的类,并将状态相关的行为委托给当前状态对象。

状态模式的结构

  1. 上下文:维护一个对当前状态对象的引用,并将与状态相关的操作委托给当前状态对象。上下文通过状态接口与状态对象交互,且会提供一个设置器用于传递新的状态对象。
  2. 状态:接口会声明特定于状态的方法,这些方法应能被其他所有具体状态所理解,因为你不希望某些状态所拥有的方法永远不会被调用。
  3. 具体状态:会自行实现特定于状态的方法,为避免多个状态相似的代码,你可以提供一个封装有部分通用行为的中间抽象类,状态对象可存储对于上下文对象的反向引用,状态可以通过该引用从上下文处获取所需信息,并且能触发状态转移。
  4. 上下文和具体状态都可以设置上下文的下一个状态,并可以通过替换链接到上下文的状态对象来完成实际的状态转移。

状态模式的工作原理

  1. 上下文对象维护一个对当前状态对象的引用。
  2. 上下文将与状态相关的请求委托给当前状态对象。
  3. 状态对象根据请求改变上下文的状态。
  4. 上下文的行为随着内部状态的改变而改变。

示例

通过一个简单的例子来理解状态模式的工作原理,假设我们有一个简单的电视机,存在两种状态:开机和关机,在不同状态下,按下电源按钮会产生不同的行为

typescript 复制代码
// 状态接口
public interface TVState{
    void pressButton(TV tv);
}

// 具体状态:开机
public class OffState implements TVState{
    @Override
 public void pressButton(TV tv){
     System.out.println("电视开机了");
  tv.setState(new OnState());
 }
}

// 具体状态:关机
public class OnState implements TVState{
    @Override
 public void pressButton(TV tv){
     System.out.println("电视关机了");
  tv.setState(new OffState());
 }
}

// 上下文:电池
public class TV{
 private TVState state;
 
 public TV(){
  //初始状态为关机
  this.state = new OffState();
 }
 
 public void setState(TVState state){
  this.state = state;
 }
 
 public void pressButton(){
  state.pressButton(this);
 }
}

// 客户端代码
public class TVDemo{
 public static void main(String[] args){
  TV tv = new TV();
  
  //第一次按下按钮,电视机开
  tv.pressButton();
  
  //第二次按下按钮,电视机关
  tv.pressButton();
 }
}

在这个示例中

  • TV 是上下文,维护对当前状态的引用。
  • TVState 是状态接口,定义了按下按钮的行为。
  • OnState 和 OffState 是具体状态,实现了按下按钮的行为。
  • 当按下按钮时,上下文将请求委托给当前状态对象,状态对象执行相应的行为并改变上下文的状态。

设计模式的重构

现在,我们回到订单处理系统,分析并对其使用状态模式进行重构。 在传统实现中,我们使用枚举表示订单状态,并在 OrderProcessor 类中使用大量的条件语句来处理不同状态下的行为,这导致了代码复杂、难以维护和扩展的问题。

使用状态模式进行重构,可以将每个订单状态封装为独立的类,并将状态相关的行为委托给当前状态对象,这样,当订单状态改变时,其行为也随之改变,而无需修改订单类本身。

重构步骤

  1. 定义一个 OrderState 接口,声明所有可能的订单状态操作。
  2. 为每个订单状态创建一个实现 OrderState 接口的具体类,如 CreatedStatePaidState 等。
  3. 增加一个 StateFactory 类,用于通过订单状态,来决定由哪个状态实现类进行逻辑处理。
  4. 修改 Order 类,增加相应状态的变更方法,以便调用 StateFactory 类中方法。

重构代码

OrderState 状态接口
java 复制代码
public interface OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean pay(Order order);

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean cancel(Order order);

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean submitForReview(Order order);

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean approve(Order order);

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean startDelivery(Order order);

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean complete(Order order);

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    boolean requestRefund(Order order);

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    String getDescription();

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    String getAvailableActions();
}
  • 定义订单状态的核心行为契约,定义了订单状态的所有可能操作,比如支付、取消、提交审核等。所有具体状态类必须实现这些方法。通过统一接口实现状态行为的封装和解耦。
状态实现类
typescript 复制代码
public class CreatedState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 支付成功");
        order.setStatus(OrderStateEnum.STATUS_PAID);
        return true;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已取消");
        order.setStatus(OrderStateEnum.STATUS_CANCELLED);
        return true;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("只有已支付的订单才能提交审核");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("只有待审核的订单才能审核通过");
        return false;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("只有已支付的订单才能开始配送");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("只有配送中的订单才能标记为完成");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("只有已完成的订单才能申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "已创建";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "支付订单、取消订单";
    }
}

public class PaidState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单已支付,无需重复支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已取消,退款处理中");
        order.setStatus(OrderStateEnum.STATUS_CANCELLED);
        return true;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已提交审核");
        order.setStatus(OrderStateEnum.STATUS_REVIEWING);
        return true;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("只有待审核的订单才能审核通过");
        return false;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 开始配送");
        order.setStatus(OrderStateEnum.STATUS_DELIVERING);
        return true;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("只有配送中的订单才能标记为完成");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("只有已完成的订单才能申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "已支付";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "提交审核、开始配送、取消订单";
    }
}

public class ReviewingState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单已支付,无需重复支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已取消,退款处理中");
        order.setStatus(OrderStateEnum.STATUS_CANCELLED);
        return true;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("订单已在审核中,无需重复提交");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 审核通过,准备配送");
        order.setStatus(OrderStateEnum.STATUS_DELIVERING);
        return true;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("订单需要先通过审核才能配送");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("只有配送中的订单才能标记为完成");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("只有已完成的订单才能申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "待审核";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "审核通过、取消订单";
    }
}

public class DeliveringState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单已支付,无需重复支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("配送重的订单无法取消");
        return false;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("订单已在配送中,无需审核");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("订单已在配送中,无需审核");
        return false;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("订单已在配送中,无需重复操作");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已送达,订单完成");
        order.setStatus(OrderStateEnum.STATUS_COMPLETED);
        return true;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("只有已完成的订单才能申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "配送中";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "完成订单";
    }
}

public class ExchangingState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单已支付,无需重复支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 已取消,退款处理中");
        order.setStatus(OrderStateEnum.STATUS_CANCELLED);
        return true;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("订单已在审核中,无需重复提交");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 审核通过,准备配送");
        order.setStatus(OrderStateEnum.STATUS_DELIVERING);
        return true;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("订单需要先通过审核才能配送");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("只有配送中的订单才能标记为完成");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("只有已完成的订单才能申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "待审核";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "审核通过、取消订单";
    }
}
public class CompletedState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("订单已完成,无需支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("已完成订单无法取消");
        return false;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("订单已完成,无需审核");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("订单已完成,无需审核");
        return false;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("订单已完成,无需配送");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("订单已完成,无需重复操作");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("订单 " + order.getOrderId() + " 申请退款中");
        // 退款逻辑
        return true;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "已完成";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "申请退款、申请换货、评价订单";
    }
}
public class CancelledState implements OrderState {

    /**
     * 支付订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean pay(Order order) {
        System.out.println("已取消订单无法支付");
        return false;
    }

    /**
     * 取消订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean cancel(Order order) {
        System.out.println("订单已取消,无需重复操作");
        return false;
    }

    /**
     * 提交订单审核
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean submitForReview(Order order) {
        System.out.println("已取消的订单无法提交审核");
        return false;
    }

    /**
     * 审核通过
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean approve(Order order) {
        System.out.println("已取消订单无法审核");
        return true;
    }

    /**
     * 开始配送
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean startDelivery(Order order) {
        System.out.println("已取消的订单无法配送");
        return false;
    }

    /**
     * 完成订单
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean complete(Order order) {
        System.out.println("已取消订单无法完成");
        return false;
    }

    /**
     * 申请退款
     *
     * @param order 订单对象
     * @return 操作是否成功
     */
    @Override
    public boolean requestRefund(Order order) {
        System.out.println("已取消的订单无法申请退款");
        return false;
    }

    /**
     * 获取状态描述
     *
     * @return 状态描述
     */
    @Override
    public String getDescription() {
        return "已取消";
    }

    /**
     * 获取可执行操作
     *
     * @return 可执行操作的描述
     */
    @Override
    public String getAvailableActions() {
        return "无可用操作";
    }
}
StateFactory
java 复制代码
public class StateFactory {

    private static final Map<OrderStateEnum, OrderState> states = new HashMap<>();

    static {

        states.put(OrderStateEnum.STATUS_CREATED, new CreatedState());
        states.put(OrderStateEnum.STATUS_PAID, new PaidState());
        states.put(OrderStateEnum.STATUS_REVIEWING, new ReviewingState());
        states.put(OrderStateEnum.STATUS_DELIVERING, new DeliveringState());
        states.put(OrderStateEnum.STATUS_COMPLETED, new CompletedState());
        states.put(OrderStateEnum.STATUS_CANCELLED, new CancelledState());

    }

    public static OrderState getState(OrderStateEnum status) {
        return states.getOrDefault(status, new CreatedState());
    }

}
  • 工厂类,用于根据订单状态枚举返回对应的状态实现类实例。静态初始化块中创建了所有状态对象的映射,getState 方法返回对应的状态,如果没有则默认返回 CreatedState
Order 上下文
typescript 复制代码
public class Order {

    /**
     * 当前状态
     */
    private OrderStateEnum status;

    /**
     * 订单ID
     */
    private String orderId;

    /**
     * 订单金额
     */
    private double amount;

    /**
     * 客户信息
     */
    private String customerInfo;

    private OrderState getState() {
        return StateFactory.getState(status);
    }

    public boolean pay() {
        return getState().pay(this);
    }

    public boolean cancel() {
        return getState().cancel(this);
    }

    public boolean submitForReview() {
        return getState().submitForReview(this);
    }

    public boolean approve() {
        return getState().approve(this);
    }

    public boolean startDelivery() {
        return getState().startDelivery(this);
    }

    public boolean complete() {
        return getState().complete(this);
    }

    public boolean requestRefund() {
        return getState().requestRefund(this);
    }

    public String getStatusDescription() {
        return getState().getDescription();
    }

    public String getAvailableActions() {
        return getState().getAvailableActions();
    }

    public Order() {
    }

    public Order(OrderStateEnum status, String orderId, double amount, String customerInfo) {
        this.status = status;
        this.orderId = orderId;
        this.amount = amount;
        this.customerInfo = customerInfo;
    }

    public OrderStateEnum getStatus() {
        return status;
    }

    public void setStatus(OrderStateEnum status) {
        this.status = status;
    }

    public String getOrderId() {
        return orderId;
    }

    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }

    public double getAmount() {
        return amount;
    }

    public void setAmount(double amount) {
        this.amount = amount;
    }

    public String getCustomerInfo() {
        return customerInfo;
    }

    public void setCustomerInfo(String customerInfo) {
        this.customerInfo = customerInfo;
    }
}
  • 订单类持有当前状态,并通过 StateFactory 获取对应的状态对象来执行操作。每个操作方法(如 paycancel )都委托给当前状态对象处理,从而实现状态转换。
测试类
csharp 复制代码
@Test
public void test_demo() {

    System.out.println("========== 测试新建订单 ==========");
    Order order = new Order(Order.STATUS_CREATED, "ORD-20250526-001", 299.99, "张三,13800138000,北京市海淀区");

    testOrderOperations(order);

    System.out.println();
    System.out.println("========== 测试已支付订单 ==========");
    order.setStatus(Order.STATUS_PAID);
    testOrderOperations(order);
}

private static void testOrderOperations(Order order) {
    System.out.println("当前状态: " + order.getStatusDescription());
    System.out.println("可用操作: " + order.getAvailableActions());

    System.out.println();
    System.out.println("尝试操作: ");
    System.out.println("支付结果: " + order.pay());
    System.out.println("取消结果: " + order.cancel());
    System.out.println("提交审核结果: " + order.submitForReview());
    System.out.println("审核通过结果: " + order.approve());
    System.out.println("开始配送结果: " + order.startDelivery());
    System.out.println("完成订单结果: " + order.complete());
    System.out.println("申请退款结果: " + order.requestRefund());

    System.out.println("操作后状态: " + order.getStatusDescription());
    System.out.println("-----------------------------------------------------");
}
运行结果
makefile 复制代码
========== 测试新建订单 ==========
当前状态: 已创建
可用操作: 支付订单、取消订单

尝试操作: 
订单 ORD-20250526-001 支付成功
支付结果: true
订单 ORD-20250526-001 已取消,退款处理中
取消结果: true
已取消的订单无法提交审核
提交审核结果: false
已取消订单无法审核
审核通过结果: true
已取消的订单无法配送
开始配送结果: false
已取消订单无法完成
完成订单结果: false
已取消的订单无法申请退款
申请退款结果: false
操作后状态: 已取消
-----------------------------------------------------

========== 测试已支付订单 ==========
当前状态: 已支付
可用操作: 提交审核、开始配送、取消订单

尝试操作: 
订单已支付,无需重复支付
支付结果: false
订单 ORD-20250526-001 已取消,退款处理中
取消结果: true
已取消的订单无法提交审核
提交审核结果: false
已取消订单无法审核
审核通过结果: true
已取消的订单无法配送
开始配送结果: false
已取消订单无法完成
完成订单结果: false
已取消的订单无法申请退款
申请退款结果: false
操作后状态: 已取消
-----------------------------------------------------

Process finished with exit code 0

长话短说

状态模式的核心思想

将对象的状态封装为独立的类,并将与状态相关的行为委托给当前状态对象。

使用场景

1. 对象行为依赖于其状态

当一个对象的行为取决于其当前状态,并且必须在运行时根据状态改变其行为时,适合使用状态模式。例如:订单处理系统、媒体播放器、工作流等。

2. 状态转换规则复杂

当状态转换规则复杂,涉及多个状态和多种状态转换时,状态模式可以使这些规则更加清晰。

3. 条件语句过多

当代码中存在大量基于对象状态的条件语句时,状态模式可以消除这些条件语句。

不适用情况

1. 状态数量少且简单

若对象只有少数几个状态,且状态转换规则简单,则使用条件判断语句更加简单和直接。

2. 状态行为差异小

如果不同状态下的行为差异小,使用状态模式可能导致过度设计。

3. 状态数量不固定

如果状态的数量不固定,或需要在运行时动态创建新状态,状态模式不是最佳选择。

实施步骤

1.识别状态和行为
  1. 识别对象的所有可能状态:列出对象可能处于的所有状态。例如,订单可能的状态有:已创建、已支付、待审核、配送中、已完成、已取消等。
  2. 识别每种状态下的行为:确定对象在每个状态下可以执行的操作和行为。例如:已创建状态下可以支付或取消,已支付状态下可以提交审核或开始配送等。
  3. 识别状态转换规则:确定状态之间的转换条件和规则。例如:只有在已创建状态下才能转换到已支付状态,且需要通过支付操作触发。
2.设计类结构
  1. 定义状态接口:创建一个状态接口,声明所有状态共有的方法。
  2. 实现具体状态类:为每个状态创建一个实现状态接口的具体类,实现特定状态下的行为和状态转换逻辑。
  3. 设计上下文类:创建一个上下文类,维护对当前状态对象的引用,并将状态相关的操作委托给当前状态对象。
3.实现状态转换
  1. 在具体状态类中实现状态转换:在具体状态类的方法中,根据需要改变上下文对象的状态。
  2. 处理非法状态转换:在不允许的状态转换中,返回错误信息或抛出异常。
相关推荐
我的炸串拌饼店3 分钟前
ASP.NET MVC 中SignalR实现实时进度通信的深度解析
后端·asp.net·mvc
挑战者6668881 小时前
springboot入门之路(一)
java·spring boot·后端
wmze2 小时前
InnoDB存储引擎
后端
99乘法口诀万物皆可变3 小时前
C#设计模式之AbstractFactory_抽象工厂_对象创建新模式-学习
设计模式·c#·抽象工厂模式
lifallen3 小时前
Java BitSet类解析:高效位向量实现
java·开发语言·后端·算法
英杰.王3 小时前
设计模式-接口隔离原则(Interface Segregation Principle, ISP)
设计模式·接口隔离原则
子恒20054 小时前
警惕GO的重复初始化
开发语言·后端·云原生·golang
daiyunchao4 小时前
如何理解"LLM并不理解用户的需求,只是下一个Token的预测,但他能很好的完成任务,比如写对你想要的代码"
后端·ai编程
Android洋芋4 小时前
SettingsActivity.kt深度解析
后端
onejason5 小时前
如何利用 PHP 爬虫按关键字搜索 Amazon 商品
前端·后端·php