DDD核心元素简介

2020-03-31  本文已影响0人  吃番茄的土拨鼠

分包示例


工程分包实现

以界限上线文为指导核心,总体分为两类 :业务界限上线文,系统界限上下文

系统界限上下文

用于放置: aop切面,通过工具包(utils),共用三方组件(mq,redis,id生成器)

业务界限上下文

按照领域划分,每个领域有一个独立的界限上线文

controller:控制器

又叫北向网关,只能将功能委托applicaton或者 reposity实现,自身只承担数据转换适配

application: 应用服务

对domain server 进行编排,控制事务,发送消息,不实现业务逻辑。需要将功能委托domain或者reposity实现

assembler

用作 DTO和do对象转换,组织网关层的数据对象(DTO,VO)入侵domain层

实例

1:验证展现层的输入
2 :将展现层对象转出领域理解的对象
3 :从reposiory获取领域对象
4: 委托领域对象执行业务处理
5:委托基础设施服务,如发送应用消息或者web调用

domain 领域

  service:领域服务

  1. 一个现实领域动作,但是并不能归属于某个领域对象,它本身可以实现业务逻辑。但是不能窃取领域对象自身的业务逻辑
  2. 领域服务负责动作编排,可以调用多个聚合根,可以调用其它领域对象

如何判断一系列交互是否属于领域
1.这种情况总是出现吗?
2.这些步骤无法分开吗?
如果这些步骤必须一起出现,就不存在’任务编排‘。他们本质上是一个整体,只是因为单一职责和分治原则需要分解,做到各个对象各司其职

  entity 实体

核心业务对象,有唯一标识,有自身的数据和动作。内部的数据完全由自身掌控,不可透传给其它对象。对象的状态完全通过动作来进行驱动

  value 值对象

通过属性而不是ID来标识和区分,是不可变对象

  factory 对象工厂

复杂对象创建

  reposity 仓储

repoisotry如何注入到domain中? 通过Factory 构建domain对象时设置

聚合根、实体、值对象对象之间如何建立关联

聚合根: 它本身不是具体的存在,它只是标识了一些作为跟对象的实体。就是说如果一个实体维护了一个领域边界,它内部包含了一些实体或者值对象,这个实体是外界访问内部信息的的唯一入口。
聚合要保持不变性

对象本身有一套对自身状态进行校验的检查条件,以确保该对象的本质不发生改变,这称之为不变式

界限上下文交互


代码示例

 public class OrderController {

        private OrderAppService orderAppService;
        private OrderRepository orderRepository;

        public OrderResp placeOrder(OrderDto orderDto) {
            OrderDo orderDo = BeanUtils.trans(orderDto, OrderDo.class);
            Long orderId = orderAppService.placeOrder(orderDo);
            return new OrderResp(orderId);
        }

        public OrderResp cancel(String orderNo) {
            orderAppService.cancelOrder(orderNo);
            return new OrderResp();
        }

        public OrderResp cancelPayment(Long orderId, Long paymentId) {
            orderAppService.cancelPayment(orderId, paymentId);
            return new OrderResp();
        }


        //直接从repo获取
        public OrderDto getOrderDetailByNo(String orderNo) {
            Order order = orderRepository.findByNo(orderNo);
            return BeanUtils.trans(order, OrderDto.class);
        }

    }

    public class OrderAppService {

        private OrderService orderService;

        private OrderRepository orderRepository;

        private OrderEventBus orderEventBus;


        public Long placeOrder(OrderDo orderDo) {
            Order order = orderService.placeOrder(orderDo);
            orderEventBus.send(new OrderEvent(EventType.PLACE.getCode(), order));
            return order.getId();
        }


        public void cancelOrder(String orderNo) {
            orderService.cancelOrder(orderNo);
            orderEventBus.send(new OrderEvent(EventType.CANCEL.getCode(), orderNo));
        }

        public void cancelPayment(Long orderId, Long paymentId) {
            Order order = orderService.cancelPayment(orderId, paymentId);
            orderEventBus.send(new OrderEvent(EventType.UPDATE.getCode(), order));
        }
    }

    public class OrderService {
        private OrderRepository orderRepository;
        private OrderFactory orderFactory;

        @Transactional(rollbackFor = RuntimeException.class)
        public Order placeOrder(OrderDo orderDo) {
            Order order = orderFactory.buildFromDo(orderDo);
            order.place();
            return order;
        }

        @Transactional(rollbackFor = RuntimeException.class)
        public void cancelOrder(String orderNo) {
            Order order = orderRepository.findByNo(orderNo);
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            order.cancel();
        }


        @Transactional(rollbackFor = RuntimeException.class)
        public Order cancelPayment(Long orderId, Long paymentId) {
            Order order = orderRepository.find(orderId);
            if (order == null) {
                throw new RuntimeException("订单不存在");
            }
            order.cancelPayment(paymentId);
            return order;
        }

    }

    @Data
    public class Order {

        private OrderRepository orderRepository;

        public void place() {
            if (this.money <= 0 || this.payments == null) {
                throw new RuntimeException("无效订单");
            }
            if (orderRepository.findByNo(this.orderNo) != null) {
                throw new RuntimeException("重复下单");
            }
            Long orderId = orderRepository.addOrder(this);

            OrderDetail orderDetail = new OrderDetail();
            orderDetail.orderId = orderId;
            orderDetail.money = this.money;
            orderDetail.status = OrderStatus.INIT.getCode();
            orderRepository.addOrderDetail(orderDetail);
        }

        public void cancel() {
            if (this.status != OrderStatus.PAY.getCode()) {
                throw new RuntimeException("订单不能撤销");
            }
            this.status = OrderStatus.CANCELED.getCode();
            orderRepository.update(this);

            OrderDetail orderDetail = new OrderDetail();
            orderDetail.orderId = this.id;
            orderDetail.money = this.money;
            orderDetail.status = OrderStatus.CANCELED.getCode();
            orderRepository.addOrderDetail(orderDetail);


        }

        public void cancelPayment(Long paymentId) {
            Payment payment = payments.stream().filter(x -> x.id.equals(paymentId)).findAny().get();
            payment.cancel();
            this.money = payments.stream().filter(x -> x.status != 1).mapToLong(x -> x.money).sum();

            orderRepository.update(this);
            orderRepository.updatePayment(payment);
        }


        private Long id;
        private String orderNo;
        private Long money;
        private Integer status;
        private List<Payment> payments;


    }

    @Getter
    @AllArgsConstructor
    public enum OrderStatus {
        INIT(1, "未支付"),
        PAYING(2, "支付中"),
        PAY(3, "已支付"),
        CANCELED(4, "已撤销");

        private int code;
        private String desc;
    }

    @Data
    public class OrderDetail {
        private Long id;
        private Long orderId;
        private Long money;
        private Integer status;

    }

    @Data
    public class Payment {

        public void cancel() {
            this.status = 1;
        }

        private Long id;
        private Long money;
        private Integer status;

    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class OrderResp {
        private Long id;
    }


    public class OrderDto {
        private Long id;
        private Long money;
        private List<PaymentDto> paymentDtos;
    }

    public class PaymentDto {
        private Long id;
        private Long money;
        private Integer status;
    }

    public class OrderDo {
        private Long id;
        private Long money;
        private List<PaymentDo> paymentDos;
    }

    public class PaymentDo {
        private Long id;
        private Long money;
        private Integer status;
    }

    public class OrderRepository {
        OrderMapper orderMapper;
        PaymentMapper paymentMapper;
        OrderDetailMapper orderDetailMapper;
        OrderFactory orderFactory;


        private Order find(Long id) {
            OrderPo order = orderMapper.find(id);
            List<PaymentPo> payments = paymentMapper.listByOrderId(id);
            return orderFactory.buildFromPo(order, payments);
        }

        private Order findByNo(String orderNo) {
            OrderPo orderPo = orderMapper.find(orderNo);
            List<PaymentPo> payments = paymentMapper.listByOrderId(orderPo.id);
            return orderFactory.buildFromPo(orderPo, payments);
        }


        void update(Order order) {
            orderMapper.update(null);
        }

        void updatePayment(Payment payment) {
            paymentMapper.updatePayemnt(null);
        }

        Long addOrder(Order order) {
            return orderMapper.insert(null);
        }

        Long addOrderDetail(OrderDetail orderDetail) {
            return orderDetailMapper.insert(orderDetail);
        }
    }

    public class OrderFactory {

        private OrderRepository orderRepository;

        public Order buildFromDo(OrderDo orderDo) {
            Order order = BeanUtils.trans(orderDo, Order.class);
            order.setOrderRepository(orderRepository);
            return order;
        }

        public Order buildFromPo(OrderPo orderPo, List<PaymentPo> paymentPos) {
            Order order = BeanUtils.trans(orderPo, Order.class);
            order.setOrderRepository(orderRepository);
            order.payments = paymentPos.stream().map(x -> {
                Payment payment = BeanUtils.trans(null, Payment.class);
                return payment;
            }).collect(Collectors.toList());
            return order;
        }
    }

    @Getter
    @AllArgsConstructor
    public enum EventType {
        PLACE(1, "下单"),
        CANCEL(2, "撤销"),
        UPDATE(3, "修改订单");
        private int code;
        private String desc;

    }


    @Data
    @AllArgsConstructor
    public class OrderEvent {
        private int type;
        private Object data;
    }

    public class OrderEventBus {

        public void send(OrderEvent event) {

        }
    }

    public interface PaymentMapper {

        List<PaymentPo> listByOrderId(Long orderId);

        int updatePayemnt(PaymentPo payment);

    }

    public interface OrderDetailMapper {

        OrderPo find(Long id);

        Long insert(OrderDetail orderDetail);
    }


    public interface OrderMapper {

        OrderPo find(Long id);

        OrderPo find(String no);

        int update(OrderPo order);

        Long insert(OrderPo order);
    }


    @Data
    public class OrderPo {
        public Long id;
        public long money;
    }

    @Data
    public class PaymentPo {
        public Long id;
        public int status;
        public Long money;
    }
上一篇 下一篇

猜你喜欢

热点阅读