DDD | 05-什么是仓储层

四、什么是仓储层?

在DDD中,仓储(Repository)是一种设计模式,它充当了领域层与数据存储层之间的桥梁。仓储的主要职责是提供一种抽象机制,使得领域对象(尤其是聚合根)可以被透明地持久化和检索,而无需暴露底层的数据访问技术细节给领域层。这样设计的目的是为了保持领域模型的纯净性,让业务逻辑不受数据访问技术的影响,同时也促进了代码的可测试性和可维护性。

主要特点

接口定义在领域层

  • 仓储接口定义了诸如保存(save)、查找(find)、更新(update)和删除(delete)领域对象的方法,这些接口属于领域层从一部分,确保了领域逻辑的独立性

实现位于基础设施层

  • 虽然仓储接口属于领域层,但它的具体实现通常位于基础设施层(Infrastructure Layer)。实现细节回依赖于具体的持久化技术,如关系数据库、NoSQL数据库、内存数据库等

隔离领域层和数据访问层

  • 通过仓储模式,领域层的对象可以不知道也不关心数据是如何存储和检索的。这有助于降低各层之间的耦合度,使得领域逻辑更加集中和纯粹

提供一致的领域对象视图

  • 仓储还负责管理领域对象的生命期,确保从存储中检索出来的对象符合领域模型的规则,例如,确保聚合的一致性

支持领域驱动设计的原则

  • Ubiquitous Language(通用语言) 、业务优先和关注点分离等原则,通过仓储的抽象,可以更好地在代码中体现业务领域的概念和规则
问题探讨

仓储层和聚合根的区别是什么?

浅显解释

聚合根

  • 想象你有一个装满东西的盒子,这个盒子就是聚合根。盒子里的东西(比如小玩具、文具等)代表聚合内的其他实体和值对象。盒子外面有个标签,写着里面有什么,这就是聚合根的标识。当你相拿走或放回盒子里的东西是,必须通过盒子(聚合根)来做,不能直接对盒子里的物品动手脚。聚合根确保盒子里的东西按规则摆放,保持整齐(即业务规则的一致性)

仓储层

  • 想象有一个大仓库,里面存放着很多这样的盒子(聚合根)。仓库管理员(仓储层)知道怎么找到每一个盒子,并且能帮你把盒子放进仓库货从仓库里拿出来。你告诉管理员需要哪个盒子,管理员就会处理好一切,你不需要知道仓库是怎么排列这些盒子的,也不用管它是用叉车还是传送带搬运的(即数据访问的具体实现)

因此,聚合根是关于管理业务对象内部的规则和结构,而仓储层是关于如何保存和获取这些业务对象到数据存储中。聚合根关注"做什么",仓储层关注"怎么存取"。

术语解释

聚合根

  • 概念:聚合根是聚合中的一个特殊实体,它作为聚合的入口点,负责维护聚合内部的一致性。聚合是一组相关对象的集合,这些对象一起被当作一个单元来对待,对外界隐藏起内部结构和复杂性
  • 职责:聚合根确保所有的业务规则在聚合内部得到遵守,它控制着对聚合内其他实体和值对象的访问。外部对象不能直接访问聚合内的非根实体,只能通过聚合根进行操作
  • 示例:在一个电子商务系统中,订单Order可能是一个聚合根,它管理者订单项OrderItem、客户信息Customer等内部实体,确保例如订单总额的计算规则得到正确执行

仓储层

  • 概念:仓储是一个设计模式,它提供了一种抽象机制,用于透明地持久化和检索领域对象,尤其是聚合根。它就像是一个集合或数据库的模拟,允许领域层以面向对象的方式操作数据,而无需关心数据存储的具体细节
  • 职责:仓储的主要职责包括保存Save、查询Find、更新Update和删除Delete聚合根。它隔离了领域层和数据访问层,使得领域逻辑可以独立于具体的数据库技术
  • 示例:在一个电子商务系统中,OrderRepository可能提供方法来查找特定ID的订单、保存新订单到数据库、更新订单状态等,而不需要订单类知道这些操作是如何与数据库交互的

区别总结

  • 目的不同:聚合根关注于业务逻辑的封装和领域内的不变性维护,而仓储关注于领域对象的持久化和检索机制
  • 层次位置:聚合根是领域层的一部分,直接参与业务逻辑的实现;仓储虽然定义在领域层,但起具体实现通常位于基础设施层,作为领域层与数据存储之间的适配层
  • 交互方式:外部组件通过仓储来操作聚合根,而不会直接操作聚合内部的其他实体。聚合根则负责维护其内部状态和业务规则的一致性

简而言之,聚合根是领域模型中的核心构造,负责业务逻辑的实现和一致性保护;而仓储是领域层与数据存储之间的中介,确保领域对象能够被持久化和检索,同时保持领域模型的纯粹性

代码示例

写一个订单仓库 (OrderRepository)


public interface OrderRepository {

    /**
     * 保存订单聚合根。
     * @param order 待保存的订单聚合根对象,包含订单的所有相关信息。
     * @return 保存后的订单聚合根对象。
     */
    OrderAggregate save(OrderAggregate order);

    /**
     * 根据订单ID查找订单聚合根。
     * @param orderId 待查找订单的唯一标识。
     * @return 如果找到,则返回包含订单信息的Optional对象;否则返回空Optional。
     */
    Optional<OrderAggregate> findById(UUID orderId);

    /**
     * 删除订单聚合根。
     * @param order 待删除的订单聚合根对象。
     */
    void delete(OrderAggregate order);

    /**
     * 更新订单状态。
     * @param orderId 待更新订单的状态的唯一标识。
     * @param newStatus 新的订单状态信息。
     */
    void updateOrderStatus(UUID orderId, OrderStatusVO newStatus);
}


写一个基于内存的订单仓库实现类OrderRepositoryImpl

public class OrderRepositoryImpl implements OrderRepository {

    /**
     * 使用HashMap存储订单聚合体,以订单ID作为键,订单聚合体作为值。
     */
    private Map<UUID, OrderAggregate> orders = new HashMap<>();

    /**
     * 保存订单聚合体。
     *
     * @param order 要保存的订单聚合体。
     * @return 返回保存的订单聚合体。
     */
    @Override
    public OrderAggregate save(OrderAggregate order) {
        orders.put(order.getOrderId(), order);
        return order;
    }

    /**
     * 根据订单ID查找订单聚合体。
     *
     * @param orderId 要查找的订单ID。
     * @return 返回找到的订单聚合体的Optional,如果找不到则为empty。
     */
    @Override
    public Optional<OrderAggregate> findById(UUID orderId) {
        return Optional.ofNullable(orders.get(orderId));
    }

    /**
     * 删除订单聚合体。
     *
     * @param order 要删除的订单聚合体。
     */
    @Override
    public void delete(OrderAggregate order) {
        orders.remove(order.getOrderId());
    }

    /**
     * 更新订单状态。
     *
     * @param orderId       要更新状态的订单ID。
     * @param newStatus     新的订单状态。
     */
    @Override
    public void updateOrderStatus(UUID orderId, OrderStatusVO newStatus) {
        Optional<OrderAggregate> optionalOrder = findById(orderId);
        optionalOrder.ifPresent(order -> {
            order.changeStatus(newStatus);
        });
    }
}

OrderRepositoryImpl在DDD中所处位置?

属于基础设施层(Infrastructure Layer)的一部分。基础设施层提供技术性服务,如数据库访问、消息传递等,以支持领域层和应用层的功能。

具体分析,OrderRepository是一个接口,它定义了如何存取领域对象OrderAggregate到持久化存储(如数据库)中。这个接口属于领域层或核心域(Core Domain),因为它表达了领域逻辑的一部分需求,即如何管理订单聚合根的存储和检索。

OrderRepositoryImpl作为接口OrderRepository的一个实现,通常驻留在基础设施层。它实现了与具体数据存储技术(如JDBC、Hibernate、Spring Data JPA等)交互的细节,确保领域层可以透过一个抽象的接口与这些底层技术解耦。这样,领域层的代码就不需要关心数据是如何被存储或检索的,从而提高了代码的可维护性和灵活性。

posted @ 2024-07-15 21:06  Neking  阅读(11)  评论(0编辑  收藏  举报