DDD代码示例

 适配层Adapter

@Api(tags = "邮箱配置")
@Slf4j
@RestController
@RequestMapping("mailConfig")
public class SysMailConfigController {

    @Autowired
    private SysMailConfigAppService sysMailConfigAppService;

    @ApiOperation("删除邮箱信息")
    @PostMapping(value = "delete.json")
    public AjaxResult<Boolean> delete(@RequestParam("id") Integer id) {
        UserInfo userInfo = UserUtils.getUserInfo();
        sysMailConfigAppService.deleteById(id, userInfo);
        return AjaxResult.success(Boolean.TRUE);
    }

    @ApiOperation("创建或更新邮箱")
    @PostMapping("createOrUpdate.json")
    public AjaxResult<Boolean> createOrUpdate(@RequestBody SysMailConfigDTO sysMailConfigDTO) {
        UserInfo userInfo = UserUtils.getUserInfo();
        sysMailConfigAppService.createOrUpdate(sysMailConfigDTO, userInfo);
        return AjaxResult.success(Boolean.TRUE);
    }

    @ApiOperation("分页查询")
    @PostMapping("listByPage.json")
    public PageResult<List<SysMailConfigVO>> listByPage(@RequestBody PageParam<SysMailConfigDTO> pageParam) {
        UserInfo userInfo = UserUtils.getUserInfo();
        return sysMailConfigAppService.selectPage(pageParam, userInfo);
    }

}

应用层Application

@Slf4j
@Service
public class SysMailConfigAppServiceImpl implements SysMailConfigAppService {

    @Autowired
    private SysMailConfigConverter sysMailConfigConverter;
    @Autowired
    private SysMailConfigDomainService sysMailConfigDomainService;

    @Override
    public PageResult<List<SysMailConfigVO>> selectPage(PageParam<SysMailConfigDTO> pageParam, UserInfo userInfo) {
        // 开启分页查询
        PageHelper.startPage(pageParam.getPage(), pageParam.getSize());

        // DTO转Model
        SysMailConfigModel sysMailConfigModel = sysMailConfigConverter.dtoToModel(pageParam.getData());

        // 查询用户列表
        List<SysMailConfigModel> sysMailConfigModelList = sysMailConfigDomainService.listByParam(sysMailConfigModel);

        // Model转VO
        List<SysMailConfigVO> sysMailConfigVOList = sysMailConfigModelList.stream().map(sysMailConfigConverter::modelToVO).collect(Collectors.toList());

        // 封装为PageInfo对象
        PageInfo<SysMailConfigVO> pageInfo = new PageInfo<>(sysMailConfigVOList);

        // 封装返回结果
        PageResult<List<SysMailConfigVO>> pageResult = new PageResult<>();
        pageResult.setTotal(pageInfo.getTotal());
        pageResult.setData(sysMailConfigVOList);
        pageResult.setSize((pageInfo.getPageSize()));
        return pageResult;
    }

    @Override
    public void createOrUpdate(SysMailConfigDTO sysMailConfigDTO, UserInfo userInfo) {
        // DTO转Model
        SysMailConfigModel sysMailConfigModel = sysMailConfigConverter.dtoToModel(sysMailConfigDTO);
        sysMailConfigDomainService.createOrUpdate(sysMailConfigModel);
    }

    @Override
    public void deleteById(Integer id, UserInfo userInfo) {
        sysMailConfigDomainService.deleteById(id);
    }

}

领域层Domain

@Slf4j
@Service
public class SysMailConfigDomainServiceImpl implements SysMailConfigDomainService {

    @Autowired
    private SysMailConfigRepository sysMailConfigRepository;

    @Override
    public void createOrUpdate(SysMailConfigModel sysMailConfigModel) {
        if (sysMailConfigModel.getId() == null) {
            sysMailConfigModel.setStatus(SysMailConfigStatusEnum.COMMON.name());
            sysMailConfigRepository.save(sysMailConfigModel);
        } else {
            sysMailConfigRepository.update(sysMailConfigModel);
        }
    }

    @Override
    public void deleteById(Integer id) {
        ValidateUtil.notNull(id, "id is null");
        SysMailConfigModel sysMailConfigModel = new SysMailConfigModel();
        sysMailConfigModel.setId(id.longValue());
        sysMailConfigModel.setStatus(SysMailConfigStatusEnum.DELETED.name());
        sysMailConfigRepository.update(sysMailConfigModel);
    }

    @Override
    public List<SysMailConfigModel> listByParam(SysMailConfigModel sysMailConfigModel) {
        return sysMailConfigRepository.listByParam(sysMailConfigModel);
    }

}

基础设施层Infrastructure

Repository仓储接口

@Slf4j
@Repository
public class SysMailConfigRepositoryImpl implements SysMailConfigRepository {

    @Autowired
    private SysMailConfigMapper sysMailConfigMapper;
    @Autowired
    private SysMailConfigConverter sysMailConfigConverter;

    @Override
    public void save(SysMailConfigModel sysMailConfigModel) {
        SysMailConfigDO sysMailConfigDO = sysMailConfigConverter.modelToDO(sysMailConfigModel);
        sysMailConfigMapper.insert(sysMailConfigDO);
    }

    @Override
    public void update(SysMailConfigModel sysMailConfigModel) {
        SysMailConfigDO sysMailConfigDO = sysMailConfigConverter.modelToDO(sysMailConfigModel);
        sysMailConfigMapper.updateById(sysMailConfigDO);
    }

    @Override
    public List<SysMailConfigModel> listByParam(SysMailConfigModel sysMailConfigModel) {
        // 分页查询
        List<SysMailConfigDO> sysMailConfigDOList = sysMailConfigMapper.listByParam(sysMailConfigModel);
        if (CollectionUtils.isEmpty(sysMailConfigDOList)) {
            return Collections.emptyList();
        }
        return sysMailConfigDOList.stream().map(sysMailConfigConverter::doToModel).collect(Collectors.toList());
    }

}
  1. 控制器层的入参和出参使用DTO(SysMailConfigDTO)和VO(SysMailConfigVO)对象进行替换,以避免直接暴露领域模型。

  2. 应用层的入参和出参也使用DTO和VO对象进行替换,同时在应用层中进行DTO和领域模型的转换。

  3. 适配层/表现层(控制器层)使用AjaxResult作为返回结果,以符合常见的RESTful API规范。

  4. 基础设施层中,持久化操作方法的返回类型改为void,以符合典型的Repository接口定义。

典型的Repository接口定义通常包括以下几个方面:

  1. 命名规范:Repository接口的命名通常以"领域实体+Repository"的方式命名,例如SysMailConfigRepository

  2. 抽象方法:Repository接口定义了对领域实体进行持久化操作的抽象方法,如saveupdatedeletefindById等。这些方法描述了对数据的常见操作。

  3. 参数类型:方法的参数类型通常是领域实体或与领域实体相关的对象,用于传递操作所需的数据。

  4. 返回类型:方法的返回类型通常是持久化操作的结果,如保存成功返回void、更新成功返回void、查询操作返回领域实体或DTO等。

  5. 异常处理:Repository接口通常会声明可能发生的异常,如数据访问异常、数据一致性异常等。这样可以提供给调用者更丰富的异常处理信息。

总体来说,典型的Repository接口定义是为了抽象和定义对领域实体进行持久化操作的方法,以提供一种统一的数据访问接口。具体的定义会根据项目需求、技术栈和团队约定而有所不同。不同的编程语言和框架也会对Repository接口定义有一些差异。重要的是根据项目的实际情况和需求,设计合适的Repository接口,使其能够满足对数据的访问和操作需求。

通常情况下,DTO、VO、DO 和 Model 可以定义在领域层,但也可以根据实际需求和项目规模进行适当的调整。

  1. DTO(Data Transfer Object):DTO 是用于在不同层之间传输数据的对象。它可以包含多个领域对象或领域模型的部分数据,并且不应该包含业务逻辑。DTO 可以定义在领域层,用于在领域层和应用层之间进行数据交互。另外,如果应用层需要将数据传输到外部系统,也可以在应用层定义相应的 DTO。

  2. VO(View Object):VO 是用于在视图层展示数据的对象,通常与特定的视图结构相关。VO 可以定义在领域层,用于在领域层和表现层之间传输数据。在实际开发中,VO 也可以定义在表现层,以与特定的视图或前端框架紧密关联。

  3. DO(Data Object):DO 是用于表示和操作外部系统的数据对象,通常与数据库或其他持久化机制相关。DO 可以定义在基础设施层,用于与数据库或其他外部系统进行数据交互。

  4. Model:Model 是用于表示业务领域概念和规则的对象,通常包含业务逻辑和领域特定的行为。Model 通常定义在领域层,作为领域模型的一部分。

在许多项目中,DTO、VO、DO 和 Model 都可以定义在领域层,以保持领域层的内聚性和独立性。这种做法可以避免将领域内部的实现细节泄露到其他层。然而,在某些特定情况下,如大型系统或需要与外部系统密切集成的系统,可能需要在其他层中定义相应的对象。

需要根据具体项目的规模、需求和团队约定来决定在哪一层定义 DTO、VO、DO 和 Model,以保持清晰的分层结构和代码的可维护性。

在DDD(领域驱动设计)中,常见的分层架构包括以下几个层:

  1. 领域层(Domain Layer):领域层是DDD的核心,包含业务规则、领域模型和领域服务等。它负责表达业务概念,封装业务逻辑,并通过领域模型来解决业务问题。领域层独立于其他层,不依赖于具体的技术实现。

  2. 应用层(Application Layer):应用层负责协调领域层和用户界面或外部接口之间的交互。它处理用户请求,调用相应的领域服务或领域模型来实现业务操作。应用层负责处理事务、权限验证、编排用例等,并与领域层进行交互。

  3. 基础设施层(Infrastructure Layer):基础设施层提供支持应用程序运行的基础设施,包括数据库、文件系统、网络通信、消息队列等。它负责将领域层和外部技术进行适配和交互。基础设施层通常包含实现与具体技术相关的代码,如数据访问、外部服务调用等。

  4. 用户界面层(User Interface Layer):用户界面层是与用户交互的接口,可以是Web界面、移动应用程序、命令行界面等。它负责接收用户输入,并将其转发给应用层处理。用户界面层也负责显示领域对象的状态和结果给用户。

这些层之间的交互遵循依赖反转和依赖规则的原则,使得依赖关系保持向内的方向,实现高内聚、低耦合的设计。领域层作为核心层包含业务规则和领域逻辑,应用层负责协调和编排领域层,基础设施层提供支持和技术实现,用户界面层与用户进行交互。这种分层架构有助于实现可维护、可测试和可扩展的应用程序。

关于DDD分层架构的依赖关系描述的有些错误。在DDD中,通常倾向于使用依赖反转(Dependency Inversion)原则,以实现高内聚、低耦合的设计。以下是修正后的依赖关系描述:

  1. 领域层(Domain Layer):

    • 领域层是整个架构的核心,应该不依赖于其他层。
    • 领域层的职责是定义领域模型、领域服务和业务规则。
  2. 应用层(Application Layer):

    • 应用层依赖于领域层,负责协调和编排领域对象的交互,但领域层不应依赖于应用层。
    • 应用层的职责是处理用户请求、事务管理、查询处理等。
  3. 基础设施层(Infrastructure Layer):

    • 基础设施层依赖于领域层和应用层,为它们提供支持和技术实现。
    • 基础设施层的职责是与外部资源(如数据库、消息队列、外部服务等)进行交互,为应用层提供数据访问和其他基础设施功能。
  4. 用户界面层(User Interface Layer):

    • 用户界面层依赖于应用层和基础设施层,负责与用户进行交互,但其他层不应依赖于用户界面层。
    • 用户界面层的职责是处理用户输入和展示数据,将用户请求转发给应用层。

总结起来,领域层是核心层,应用层依赖于领域层,基础设施层依赖于领域层和应用层,用户界面层依赖于应用层和基础设施层。依赖关系应该遵循依赖反转原则,高层次的模块(如用户界面层)不应依赖于低层次的模块,而是通过接口进行交互。这样可以实现解耦、可测试和可扩展的架构设计。非常抱歉之前的描述会引起困惑,希望这次的修正能更准确地回答您的问题。

在DDD中,client层表示与外部客户端应用程序交互的层。这个层负责处理来自外部客户端的请求,并将其转发给应用层进行处理。client层可以包括各种类型的客户端,如Web界面、移动应用程序、命令行界面等。

依赖关系中,client层依赖于应用层和基础设施层,负责与外部客户端进行交互。它可以调用应用层的接口或服务来处理客户端请求,并将结果返回给客户端。

总结起来,完整的DDD分层架构包括以下层:

  1. 领域层(Domain Layer):核心业务逻辑和领域模型。
  2. 应用层(Application Layer):协调和编排领域层的交互。
  3. 基础设施层(Infrastructure Layer):提供支持和技术实现,如数据库、外部服务等。
  4. 用户界面层(User Interface Layer):处理用户输入和展示数据。
  5. Client层(Client Layer):与外部客户端应用程序进行交互。

这样的分层架构可以帮助实现高内聚、低耦合的设计,支持可维护、可测试和可扩展的应用程序。非常抱歉之前的遗漏,希望这次的回答更准确和完整。

在DDD的分层架构中,用户界面层依赖于Client层,用于与外部客户端应用程序进行交互。客户端可以是Web界面、移动应用程序、命令行界面等。

正确的依赖关系是:

  1. 用户界面层(User Interface Layer):

    • 用户界面层依赖于Client层和应用层。
    • 用户界面层负责处理用户输入和展示数据,与Client层进行交互,通过调用Client层的接口或服务与外部客户端进行通信。
    • 用户界面层可能包含用户界面逻辑、视图模型(ViewModel)等。
  2. Client层(Client Layer):

    • Client层是与外部客户端应用程序交互的层。
    • Client层依赖于应用层和基础设施层,负责处理来自用户界面层的请求,并将其转发给应用层进行处理。
    • Client层可以封装与外部客户端的通信细节,例如通过API调用或其他协议与外部客户端进行交互。

这样的依赖关系确保了用户界面层能够通过Client层与外部客户端进行交互,并将用户的请求转发给应用层进行处理。

感谢您的指正,再次对之前的错误回答表示歉意。如果还有其他问题,请随时提问。

  • 11
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里是一个简单的 Java 实现 DDD代码示例: 首先,我们需要定义一个领域对象(Domain Object),比如一个订单对象: ```java public class Order { private String orderId; private String customerId; private List<OrderItem> orderItems; private OrderStatus status; public Order(String orderId, String customerId, List<OrderItem> orderItems) { this.orderId = orderId; this.customerId = customerId; this.orderItems = orderItems; this.status = OrderStatus.NEW; } public void cancel() { this.status = OrderStatus.CANCELLED; } public void complete() { this.status = OrderStatus.COMPLETED; } // getters and setters } public enum OrderStatus { NEW, COMPLETED, CANCELLED } public class OrderItem { private String productId; private int quantity; public OrderItem(String productId, int quantity) { this.productId = productId; this.quantity = quantity; } // getters and setters } ``` 然后,我们需要定义一个领域服务(Domain Service),比如一个订单服务: ```java public class OrderService { private OrderRepository orderRepository; public OrderService(OrderRepository orderRepository) { this.orderRepository = orderRepository; } public void createOrder(String customerId, List<OrderItem> orderItems) { String orderId = UUID.randomUUID().toString(); Order order = new Order(orderId, customerId, orderItems); orderRepository.save(order); } public void cancelOrder(String orderId) { Order order = orderRepository.findById(orderId); order.cancel(); orderRepository.save(order); } public void completeOrder(String orderId) { Order order = orderRepository.findById(orderId); order.complete(); orderRepository.save(order); } } ``` 最后,我们需要定义一个仓储接口(Repository Interface),比如一个订单仓储: ```java public interface OrderRepository { Order findById(String orderId); void save(Order order); void delete(Order order); } ``` 以上就是一个简单的 DDD 实现的 Java 代码示例。在这个示例中,我们将领域对象和领域服务分离开来,通过仓储接口将领域对象持久化到数据库中,实现了领域模型的独立性和可维护性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值