0

0

在Java中如何设计领域对象模型_Java业务建模解析

P粉602998670

P粉602998670

发布时间:2026-01-10 16:20:06

|

474人浏览过

|

来源于php中文网

原创

ddd在java中落地的核心是让领域对象承载业务语义:封装行为而非仅数据,值对象不可变且重写equals/hashcode,聚合根明确边界并隔离持久化细节。

在java中如何设计领域对象模型_java业务建模解析

Domain-Driven Design(DDD)在 Java 中落地,核心不是堆砌注解或套用框架,而是让对象真正承载业务语义。领域对象模型不是数据库表的镜像,也不是 DTO 的变体,它得能回答“这个对象能做什么”“它什么时候是合法的”“它的状态如何被改变”。

领域对象必须封装行为,不能只有 getter/setter

很多团队把 Order 类写成纯数据容器:一堆 private 字段 + public getter/setter。这导致业务逻辑散落在 OrderService 里,Order 自身无法表达“订单可以取消”“已发货的订单不能改地址”这类规则。

正确做法是把校验和状态变更逻辑收进领域对象内部:

public class Order {
    private OrderStatus status;
    private Address shippingAddress;

    public void changeShippingAddress(Address newAddress) {
        if (status == OrderStatus.SHIPPED) {
            throw new IllegalStateException("Cannot modify address after shipment");
        }
        this.shippingAddress = newAddress;
    }

    public void cancel() {
        if (status == OrderStatus.CANCELLED) return;
        if (status == OrderStatus.SHIPPED) {
            throw new IllegalStateException("Shipped order cannot be cancelled");
        }
        this.status = OrderStatus.CANCELLED;
    }
}

关键点:

  • changeShippingAddress()cancel() 是命令方法,不是 setter;它们隐含前置条件与副作用
  • 字段保持 private,不暴露 setStatus() 这类危险接口
  • 构造函数应强制满足基本不变量(如 orderId 非空、创建时间必设)

值对象(Value Object)要不可变且重写 equals/hashCode

MoneyAddressPhoneNumber 这类对象,本质是“值”,不是“身份”。Java 中常见错误是把它做成可变类,或直接用 String 代替。

立即学习Java免费学习笔记(深入)”;

例如:Address 若可变,两个订单共用同一 Address 实例,一处改了街道,另一处也跟着变——这不是业务事实,是 bug。

正确实现要点:

  • 所有字段 final,构造后不可变
  • 不提供 setter,也不暴露可变集合(如返回 Collections.unmodifiableList()
  • 必须重写 equals()hashCode(),基于字段内容比较(IDE 可自动生成)
  • 推荐使用记录类(record)简化: public record Address(String street, String city, String zipCode) {}

聚合根(Aggregate Root)要控制边界和一致性

一个常见误区是把整个订单系统建模为单个大聚合:把 OrderOrderItemPaymentLogEntry 全塞进一个 @Aggregate 注解里。结果是并发更新冲突频繁、持久化性能差、事务太长。

秀脸FacePlay
秀脸FacePlay

一款集成AI换脸、照片跳舞等多种AI特效玩法的App

下载

聚合根的核心职责是:维护其内部实体/值对象之间的一致性约束,并对外提供唯一访问入口。

例如:

  • Order 是聚合根,OrderItem 是其内部实体,生命周期依附于订单
  • Payment 应是独立聚合,有自己 ID 和生命周期;订单只持有一个 paymentId 引用,而非嵌入整个 Payment 对象
  • 跨聚合的操作(如“支付成功后更新订单状态”)必须通过领域事件或应用层协调,不能在 Order 内部直接调用 payment.confirm()

否则会模糊边界,导致测试困难、数据库耦合、分布式事务陷阱。

JPA/Hibernate 不是领域模型的默认载体

直接用 @Entity 标记领域对象,很快会遇到矛盾:

  • JPA 要求无参构造函数,但领域对象应通过有参构造保证合法性
  • @OneToMany 加载策略常导致 N+1 查询,而领域层不该暴露这种技术细节
  • 为了映射方便加 @Transient@JsonIgnore,污染了领域语义

更稳健的做法是分层隔离:

  • 领域层定义纯净的 OrderOrderItem,不含任何 JPA 注解
  • 持久化层用单独的 OrderJpaEntity 映射表结构,由仓储(OrderRepository)负责在两者间转换
  • 转换逻辑放在仓储实现内,而非领域对象中(避免引入 javax.persistence 包)

这样,当你需要换数据库、加缓存、切分微服务时,领域模型本身不受影响。

最难的不是写出符合 DDD 术语的类,而是每次加一个字段、改一个方法时,都问一句:这个改动是否改变了业务含义?它是否破坏了某个不变量?有没有人会在别处绕过这个逻辑?

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
什么是分布式
什么是分布式

分布式是一种计算和数据处理的方式,将计算任务或数据分散到多个计算机或节点中进行处理。本专题为大家提供分布式相关的文章、下载、课程内容,供大家免费下载体验。

404

2023.08.11

分布式和微服务的区别
分布式和微服务的区别

分布式和微服务的区别在定义和概念、设计思想、粒度和复杂性、服务边界和自治性、技术栈和部署方式等。本专题为大家提供分布式和微服务相关的文章、下载、课程内容,供大家免费下载体验。

251

2023.10.07

hibernate和mybatis有哪些区别
hibernate和mybatis有哪些区别

hibernate和mybatis的区别:1、实现方式;2、性能;3、对象管理的对比;4、缓存机制。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

158

2024.02.23

Hibernate框架介绍
Hibernate框架介绍

本专题整合了hibernate框架相关内容,阅读专题下面的文章了解更多详细内容。

93

2025.08.06

Java Hibernate框架
Java Hibernate框架

本专题聚焦 Java 主流 ORM 框架 Hibernate 的学习与应用,系统讲解对象关系映射、实体类与表映射、HQL 查询、事务管理、缓存机制与性能优化。通过电商平台、企业管理系统和博客项目等实战案例,帮助学员掌握 Hibernate 在持久层开发中的核心技能。

39

2025.09.02

Hibernate框架搭建
Hibernate框架搭建

本专题整合了Hibernate框架用法,阅读专题下面的文章了解更多详细内容。

72

2025.10.14

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1010

2023.08.02

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1902

2023.10.19

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

22

2026.03.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.3万人学习

C# 教程
C# 教程

共94课时 | 11.1万人学习

Java 教程
Java 教程

共578课时 | 80.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号