【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼?

前言

之前在我的博客(一枝花算不算浪漫)中已经更新过两篇设计模式相关的内容

上面内容都是基于真实业务场景精简后的设计(工作中真实场景使用到的)。

之前为了学习设计模式,看过网上很多相关博客讲解,大都是画下UML类图,举例几个毫不相干的demo,看了几遍仍然是云里雾里。

因为自己现在做的项目就是属于B2C的商城,项目中使用到了大量的设计模式,所以这里精简真实的业务场景,将核心的业务代码抽离出来。代码不涉及任何公司信息,所有敏感信息都已屏蔽,代码只用作学习交流使用。

业务场景

一图流,首先看下提交订单 我们抽象出的一些场景:

订单中心:
1、订单中心创建订单
2、订单状态流转(状态模式)
3、记录操作日志(装饰器模式+简单工厂模式)
4、订单中心通知 库存中心更新库存

调度中心:
1、库存中心更新本地库存(使用命令模式+模板方法模式+工厂模式)
这个上讲已经说过:【一起学设计模式】命令模式+模板方法+工厂方法实战: 如何优雅的更新商品库存...
2、将更新库存数据放到消息中,调度中心消费消息(中介模式)
3、放入消息队列中,判断队列是否放满了,如果放满了需要建立离线存储(备忘录模式)
4、异步监听消息处理结果(观察者模式)

这个模型应该很简单,我们来一步步拆解 一步步代码分析

订单状态流转 + 操作日志记录

代码实现

  1. 订单中心提交订单操作

    /**
    * 订单状态管理器
    */
    @Autowired
    private LoggedOrderStateManager orderStateManager;
    
    public OrderInfoDTO save(OrderInfoDTO order) throws Exception {
        // 检查库存是否充足
        if(!isStockEnough(order)) {
            return order;
        }
    
        // 将订单信息保存到本地数据库
        saveOrder(order);
        // 订单状态流转
        orderStateManager.create(order); 
    
        // other logic
        return order;
    }
  2. 订单状态管理器
    /**
     * 会自动记录日志的订单状态管理器
     * @author wangmeng
     *
     */
    @Component
    public class LoggedOrderStateManager implements OrderStateManager {
    
        /**
         * 订单状态管理器
         */
        @Autowired
        private OrderStateManagerImpl orderStateManager;
    
        /**
         * 订单操作日志DAO组件
         */
        @Autowired
        private OrderOperateLogDAO orderOperateLogDAO;
    
        /**
         * 订单操作内容工厂
         */
        @Autowired
        private OrderOperateLogFactory orderOperateLogFactory;
    
        @Override
        public void create(OrderInfoDTO order) throws Exception {
            orderStateManager.create(order);
            orderOperateLogDAO.save(orderOperateLogFactory.get(order, OrderOperateType.CREATE_ORDER));
        }
    
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return orderStateManager.canCancel(order);
        }
    
        @Override
        public void cancel(OrderInfoDTO order) throws Exception {
            orderStateManager.cancel(order);
            orderOperateLogDAO.save(orderOperateLogFactory.get(order, OrderOperateType.CANCEL_ORDER));
        }
    }
  3. 日志操作工厂
    /**
     * 订单操作内容工厂
     * @author wangmeng
     *
     */
    @Component
    public class OrderOperateLogFactory {
    
        /**
         * 日期辅助组件
         */
        @Autowired
        private DateProvider dateProvider;
    
        /**
         * 获取订单操作内容
         * @param operateType 订单操作类型
         * @return 订单操作内容
         */
        public OrderOperateLogDO get(OrderInfoDTO order, Integer operateType) throws Exception {
            String operateContent = null;
    
            if(OrderOperateType.CREATE_ORDER.equals(operateType)) {
                operateContent = "完成订单创建,订单编号为:" + order.getOrderNo();
            } else if(OrderOperateType.CANCEL_ORDER.equals(operateType)) {
                operateContent = "取消订单,订单编号为:" + order.getOrderNo();
            } else if(OrderOperateType.PAY_ORDER.equals(operateType)) {
                operateContent = "支付订单,订单编号为:" + order.getOrderNo() + ",支付金额为:" + order.getPayableAmount();
            } else if(OrderOperateType.GOODS_DELIVERY.equals(operateType)) {
                operateContent = "已经将订单中的商品进行发货";
            } else if(OrderOperateType.CONFIRM_RECEIPT.equals(operateType)) {
                operateContent = "完成确认收货";
            } else if(OrderOperateType.APPLY_RETURN_GOODS.equals(operateType)) {
                operateContent = "申请退货";
            } else if(OrderOperateType.RETURN_GOODS_REJECTED.equals(operateType)) {
                operateContent = "退货申请审核不通过";
            } else if(OrderOperateType.RETURN_GOODS_APPROVED.equals(operateType)) {
                operateContent = "退货申请审核已通过";
            } else if(OrderOperateType.SEND_OUT_RETURN_GOODS.equals(operateType)) {
                operateContent = "寄送退货商品";
            } else if(OrderOperateType.CONFIRM_RETURN_GOODS_RECEIPT.equals(operateType)) {
                operateContent = "确认收到退货商品";
            } else if(OrderOperateType.FINISHED_RETURN_GOODS_INPUT.equals(operateType)) {
                operateContent = "完成退货商品入库";
            } else if(OrderOperateType.FINISHED_RETURN_GOODS_REFUND.equals(operateType)) {
                operateContent = "完成退款";
            }     
    
            OrderOperateLogDO log = create(order, operateType, operateContent);
            return log;
        }
    
        /**
         * 创建订单操作日志
         * @param operateType 订单操作类型
         * @param operateContent 订单操作内容
         * @return 订单操作日志
         * @throws Exception
         */
        private OrderOperateLogDO create(OrderInfoDTO order ,
                Integer operateType, String operateContent) throws Exception {
            OrderOperateLogDO log = new OrderOperateLogDO();
    
            log.setOrderInfoId(order.getId());
            log.setOperateType(operateType);
            log.setOperateContent(operateContent);
            log.setGmtCreate(new Date());
            log.setGmtModified(new Date());
            return log;
        }
    
    }
  4. 订单状态流转
    我们只列出来订单create和cacel两种状态,因为状态流转时要判断当前状态是否可以流转到下一个状态,所以这里还有一个canCancel方法。

    /**
     * 订单状态管理器接口
     * @author wangmeng
     *
     */
    interface OrderStateManager {
    
        /**
         * 创建订单
         * @param order 订单
         * @throws Exception
         */
        void create(OrderInfoDTO order) throws Exception;
    
        /**
         * 订单能否执行取消操作
         * @param order 订单
         * @return 能否执行取消操作
         * @throws Exception
         */
        Boolean canCancel(OrderInfoDTO order) throws Exception;
    
        /**
         * 执行取消订单操作
         * @param order 订单
         * @throws Exception
         */
        void cancel(OrderInfoDTO order) throws Exception;
    
        // 这里还会有更多的订单状态:支付、确认收货、发货、退货等等状态流转
    }
  5. OrderStateManager实现类
    /**
     * 订单状态管理器
     * @author wangmeng
     *
     */
    @Component
    public class OrderStateManagerImpl implements OrderStateManager {
    
        /**
         * 已取消状态
         */
        @Autowired
        private CanceledOrderState canceledOrderState;
    
        /**
         * 待付款状态
         */
        @Autowired
        private WaitForPayOrderState waitForPayOrderState;
    
        /**
         * 创建订单
         * @param order 订单
         * @throws Exception
         */
        @Override
        public void create(OrderInfoDTO order) throws Exception {
            waitForPayOrderState.doTransition(order);
        }
    
        /**
         * 订单能否执行取消操作
         * @param order 订单
         * @return 能否执行取消操作
         * @throws Exception
         */
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return getOrderState(order).canCancel(order);
        }
    
        /**
         * 执行取消订单操作
         * @param order 订单
         * @throws Exception
         */
        @Override
        public void cancel(OrderInfoDTO order) throws Exception {
            canceledOrderState.doTransition(order);
        }
    
        /**
         * 获取订单状态组件
         * @param order 订单
         * @return 订单状态组件
         * @throws Exception
         */
        private OrderState getOrderState(OrderInfoDTO order) throws Exception {
            if(OrderStatus.WAIT_FOR_PAY.equals(order.getOrderStatus())) {
                return waitForPayOrderState;
            } else if(OrderStatus.CANCELED.equals(order.getOrderStatus())) {
                return canceledOrderState;
            } else if(OrderStatus.WAIT_FOR_DELIVERY.equals(order.getOrderStatus())) {
                return waitForDeliveryOrderState;
            } else if(OrderStatus.WAIT_FOR_RECEIVE.equals(order.getOrderStatus())) {
                return waitForReceiveOrderState;
            } else if(OrderStatus.FINISHED.equals(order.getOrderStatus())) {
                return finishedOrderState;
            } else if(OrderStatus.WAIT_FOR_RETURN_GOODS_APPROVE.equals(order.getOrderStatus())) {
                return waitForReturnGoodsApproveOrderState;
            }
            return defaultOrderState;
        }
    }

    OrderState:

    /**
     * 订单状态
     * @author wangmeng
     *
     */
    public interface OrderState {
    
        /**
         * 订单流转到当前这个状态
         * @param order 订单
         * @throws Exception
         */
        void doTransition(OrderInfoDTO order) throws Exception;
    
        /**
         * 判断当前状态下能否执行取消订单操作
         * @param order 订单
         * @return 能否执行取消订单操作
         * @throws Exception
         */
        Boolean canCancel(OrderInfoDTO order) throws Exception;
    }

    WaitForPayOrderState:

    /**
     * 待付款状态
     * @author wangmeng
     *
     */
    @Component
    public class WaitForPayOrderState extends AbstractOrderState {
    
        @Autowired
        public WaitForPayOrderState(DateProvider dateProvider, OrderInfoDAO orderInfoDAO) {
            super(dateProvider, orderInfoDAO);
        }
    
        @Override
        protected Integer getOrderStatus(OrderInfoDTO order) throws Exception {
            return OrderStatus.WAIT_FOR_PAY;
        }
    
        @Override
        public Boolean canPay(OrderInfoDTO order) throws Exception {
            return true;
        }
    
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return true;
        }
    }

    AbstractOrderState:

    
    /**
     * 订单状态的抽象基类
     * @author wangmeng
     *
     */
    public abstract class AbstractOrderState implements OrderState {
    
        /**
         * 订单管理DAO组件
         */
        protected OrderInfoDAO orderInfoDAO;
    
        public AbstractOrderState(OrderInfoDAO orderInfoDAO) {
            this.orderInfoDAO = orderInfoDAO;
        }
    
        /**
         * 订单流转到当前这个状态
         * @param order 订单
         */
        @Override
        public void doTransition(OrderInfoDTO order) throws Exception {
            Integer orderStatus = getOrderStatus(order);
            order.setOrderStatus(orderStatus);
            orderInfoDAO.updateStatus(order.getId(), orderStatus);
        }
    
        /**
         * 获取订单状态
         * @param order 订单
         * @return 订单状态
         * @throws Exception
         */
        protected abstract Integer getOrderStatus(OrderInfoDTO order) throws Exception;
    
        /**
         * 判断当前状态下能否执行取消订单操作
         * @param order 订单
         * @return 能否执行取消订单操作
         */
        @Override
        public Boolean canCancel(OrderInfoDTO order) throws Exception {
            return false;
        }
    }

总结

上面只是讲了 订单中心提交订单中使用了状态模式简单工厂模式装饰器模式

状态模式:OrderStat + OrderStateManager等
简单工厂模式:OrderOperateLogFactory
装饰器模式:LoggedOrderStateMananger

其中LoggedOrderStateMananger实现了OrderStateManager接口,增强了create、cancel、pay等方法的实现,添加了记录日志的功能,使得状态流转后 可以自动记录日志的功能。

这里只是将精简后的代码提供出来,我相信认真看一下还是很易懂的,后面还有提交订单 后面的一些流程,会单独在开一片文章来讲解,敬请期待。

申明

本文章首发自本人博客:https://www.cnblogs.com/wang-meng 和公众号:壹枝花算不算浪漫,如若转载请标明来源!

感兴趣的小伙伴可关注个人公众号:壹枝花算不算浪漫

原文地址:https://www.cnblogs.com/wang-meng/p/12038619.html

时间: 2024-12-23 18:19:26

【一起学设计模式】状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼?的相关文章

【一起学设计模式】中介者模式+观察者模式+备忘录模式实战:(二)提交个订单我到底经历了什么鬼?

前言 再多的话就不说了,这个是接着上一讲: [一起学设计模式]状态模式+装饰器模式+简单工厂模式实战:(一)提交个订单我到底经历了什么鬼? 一起的,一些多余的赘述请先看这个篇文章. 业务场景 一图流,还是上一篇文章中一样的图,接下来我们就梳理下总结模式.观察者模式.备忘录模式的应用: 订单中心: 1.订单中心创建订单 2.订单状态流转(状态模式) 3.记录操作日志(装饰器模式+简单工厂模式) 4.订单中心通知 库存中心更新库存 调度中心: 1.库存中心更新本地库存(使用命令模式+模板方法模式+工

设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)

什么是简单工厂模式? 从设计模式的类型上来说,简单工厂模式是属于创建型模式,又叫做静态工厂方法(Static Factory Method)模式,通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类. 简单工厂模式在cocos2d-x中怎么用,我们通过下面的小例子来了解一下. 假如我们在开发一款类似魔兽的RPG游戏,在游戏中会出现很多种族的角色,如:人族.兽族. 这些种族一般都会定义为一个类,如果兽族Orc类,人族Human类. 兽族.人族两个类都同样属于种族,那么我们可以

《大话设计模式》学习笔记系列--1. 简单工厂模式

简单工厂模式实现了一种"工厂"概念的面向对象设计模式,它可以在不指定对象具体类型的情况下创建对象.其实质是定义一个创建对象的接口,但让实现这个接口的类来决定实例化具体类.工厂方法让类的实例化推迟到子类中进行. 以书本上的计算器程序为例,其UML描述如下: 图中,AddOperator, SubtactOpertor继承算式基类Operator,而CreateOperator则是负责创建一个操作类,而不指明具体的子类类型. 下面,我们来看代码: 首先操作积累: /// <summa

(二)设计模式之PHP项目应用(简单工厂模式:计算器)

1 简单工厂模式简介 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类(这些产品类继承自一个父类或接口)的实例. 2 模式组成 1)工厂(Creator)角色 简单工厂模式的核心,它负责实现创建所有实例的内部逻辑.工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象. 2)抽象产品(Product)角色 简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口. 3)具体产品(Concrete Product)角色 是简单工厂模式的创建目标,所

设计模式学习笔记(二)--简单工厂模式和工厂模式

老生长谈的两个设计模式了,这里把这两个设计模式对比着来总结一下. 什么是简单工厂模式? 简单工厂模式:根据传入工厂类的参数动态决定要创建哪一个产品类的实例. UML图如下(以实现一个计算器为例): 简单工厂模式的Java代码实现如下: 1 package designPattern; 2 /** 3 * 简单工厂模式 4 * @author yiRain 5 * 6 */ 7 public class SimpleFactory { 8 9 public static void main(Str

模式设计学习 之 简单工厂模式

有幸看到园友推荐的 <大话设计模式>十分感谢,准备练习一下,以免忘记. 设计模式 需要灵活运用,不能为了 设计而设计,这样就得不偿失了. 简单工厂模式 又叫做 静态方法 模式 ,不在 23 种 设计模式之内 .是项目中最简单实用的 模式.它避免了大量的 代码 写在 一起 造成的 项目混乱,实现了简单的分层. 可以使用户只关心 使用 ,传入参数 调用方法. 缺点 是 大量的 业务 逻辑 处理 写在同一个 工厂 内, 当 需求发生 变动时,需要去修改工厂内的方法,这样违反了开放封闭原则. 写个例子

《大话设计模式》ruby版代码:简单工厂模式

之前有看过<ruby设计模式>,不过渐渐的都忘记了.现在买了一个大话设计模式,看起来不是那么枯燥,顺便将代码用ruby实现了一下. # -*- encoding: utf-8 -*- #运算类 class Operation attr_accessor :number_a,:number_b def initialize(number_a = nil, number_b = nil) @number_a = number_a @number_b = number_b end def resul

设计模式之一(简单工厂模式)

简单工厂模式 说先说一下我们熟悉的23中设计模式划分: 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. 行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 其实还有两类:并发型模式和线程池模式. 今天只要是针对简单工厂模式给大家讲解一下.直

[python实现设计模式]-3.简单工厂模式

预备知识: 开放封闭原则(Open-Closed Principle OCP) Software entities(classes,modules,functions etc) should open for extension ,but close for modification. 所谓开放封闭原则就是软件实体应该对扩展开放,而对修改封闭.开放封闭原则是所有面向对象原则的核心. 软件设计本身所追求的目标就是封装变化,降低耦合,而开放封闭原则正是对这一目标的最直接体现. 对扩展开放,意味着有新