一个简单的订单状态模式实现

在一般的订单模块中,订单状态是不可或缺的一个因素,订单状态因为业务需要的原因有多种实现,为了避免臃肿和混乱不清的代码结构,我们可以尝试将订单状态的变更抽象出来,单独做变更。

其中设计状态变更的前置代码,亦可在状态模式中处理,(比如订单从未支付到支付,需要去调用第三方支付接口或者其他实现,这个实现就可以在订单状态变更的内部实现。)

创建订单类,作为数据载体:

java 复制代码
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Order {

    // 状态类
    private OrderState orderState;

    // 订单号
    private String orderNo;

    // 订单状态
    private String status;
}

创建订单状态接口:如果不再细分的话,可以将订单所有涉及状态变更的操作都抽象成方法在这里列出来

java 复制代码
public interface OrderState {

    // 提交订单
    OrderState submit();

    // 支付
    OrderState pay();

    // 取消
    OrderState cancel();

    // 再来一单
    OrderState reBuy();
    
    // 其他订单操作...
}

创建状态接口所有方法的默认处理方式(后面我们具体的订单状态类将继承此抽象类,在这里设置过默认处理后,我们的状态类也不需要实现全部的方法了)

java 复制代码
@Data
@AllArgsConstructor
public abstract class AstractOrderState implements OrderState {

    // 我们要处理的数据
    private Order order;

    /**
    * 根据数据库的状态枚举获取状态类实例
    */
    public static OrderState getOrderStateByState(Order order) {
        switch (order.getStatus()) {
            case "NOSUBMIT":
                return new NotSubmitted(order);
            case "WAITPAY":
                return new WaitPay(order);
            default:
                throw new RuntimeException("状态未知" + order.getStatus());
        }
    }

    @Override
    public OrderState submit() {
        System.out.println("当前状态为:" + this.order.getStatus() + ",不支持提交操作");
        return this;
    }

    @Override
    public OrderState pay() {
        System.out.println("当前状态为:" + this.order.getStatus() + ",不支持付款操作");
        return this;
    }

    @Override
    public OrderState cancel() {
        System.out.println("当前状态为:" + this.order.getStatus() + ",不支持取消操作");
        return this;
    }

    @Override
    public OrderState reBuy() {
        System.out.println("当前状态为:" + this.order.getStatus() + ",不支持再来一单操作");
        return this;
    }
}

创建各个状态的对象,以及编写改对象的代码:

java 复制代码
// 未提交状态
public class NotSubmitted extends AstractOrderState {

    public NotSubmitted(Order order) {
        super(order);
    }
    
    @Override
    public OrderState submit(){
        System.out.println("当前状态:" + this.getOrder().getStatus()+" 已提交");
        // 订单提交代码
        return new Submitted(this.getOrder());
    }

    @Override
    public OrderState cancel(){
        System.out.println("当前状态:" + this.getOrder().getStatus());
        // 订单提交代码
        return new Cancelled(this.getOrder());
    }
}
java 复制代码
// 待支付状态
public class WaitPay extends AstractOrderState {

    public WaitPay(Order order) {
        super(order);
    }
    
    @Override
    public OrderState pay(){
        System.out.println("当前状态:" + this.getOrder().getStatus());
        // 支付代码
        return new Paid(this.getOrder());
    }
    
    @Override
    public OrderState cancel(){
        System.out.println("当前状态:" + this.getOrder().getStatus());
        // 订单提交代码
        return new Cancelled(this.getOrder());
    }
}
java 复制代码
// 订单已完成状态
public class Done extends AstractOrderState {
    
    public Done(Order order) {
        super(order);
    }
    
    @Override
    public OrderState reBuy(){
        System.out.println("当前状态:" + this.getOrder().getStatus());
        // 再次购买代码
        return new NotSubmitted(this.getOrder());
    }
    
    @Override
    public OrderState cancel(){
        System.out.println("当前状态:" + this.getOrder().getStatus());
        // 订单提交代码
        return new Cancelled(this.getOrder());
    }
}

从代码中我们可以看出,不同的状态类只需要实现自己所能处理的方法即可,这样我们就将不同状态的职责划分给不同状态类了,这可以帮助我们更好的处理订单状态变更,当然这只是一个demo,想要使用订单状态模式去处理自己的需求还需要大家根据自己的工作需求去写不同的实现。归根到底这种设计模式只是将看似有共同点的不同处理划分成一类,然后再在此类中细分,如果我们有其他的类似需求也是可以用到上述设计模式的。

测试:

java 复制代码
public class OrderController {
    public static void main(String[] args) {
        Order order = Order.builder()
                .status("NOSUBMIT")
                .build();
        order.setOrderState(AstractOrderState.getOrderStateByState(order));
        order.getOrderState().reBuy();
    }
}

这里我们创建一个未提交状态的订单,并且让他调用reBuy()方法,发现此状态没有实现reBuy()方法,代码就会走到我们的默认方法中,然后报错:

java 复制代码
public class OrderController {
    public static void main(String[] args) {
        Order order = Order.builder()
                .status("NOSUBMIT")
                .build();
        order.setOrderState(AstractOrderState.getOrderStateByState(order));
        order.getOrderState().submit();
    }
}

当我们使用未提交状态去调用提交方法时,因为未提交状态类实现了此方法,就会走该实现,正常打印结果。

相关推荐
Zane19943 天前
一个 new 就能创建对象,为什么还要拆出单例、工厂、建造者、原型四种模式?
设计模式
怕浪猫4 天前
一行命令复刻爆款视频,我把 Hypit 从安装跑到了出片
人工智能·设计模式·程序员
Zane19944 天前
函数式编程里的函数,其实不是你天天写的那个函数——三大编程范式的边界在哪
设计模式
Zane19945 天前
策略模式现在该不该上?一次讲清楚过度设计和设计不足怎么找平衡
设计模式
她说..5 天前
常见设计模式-模板方法模式
java·spring·设计模式·springboot
xiaofeiyang1506 天前
第六章 · 桥接 — 三支毛笔,画出九种颜色
设计模式
Shadow(⊙o⊙)6 天前
OTOL设计模式 One Thread One Loop
服务器·网络·设计模式
sarasuki7 天前
如何让LLM 能在半夜偷偷打开网易云呢?
人工智能·设计模式·agent
小王师傅667 天前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
执明wa7 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio