前言
java 中的 ddd 指的是 领域驱动设计(domain-driven design),它是一种软件开发方法论,强调以业务领域为核心来设计和构建复杂系统。ddd 并不是一种框架或技术,而是一种设计思想和架构理念,特别适用于业务逻辑复杂、核心领域价值高的系统(如金融、电商、erp 等)。
什么是 ddd(domain-driven design)?
“把软件的焦点放在核心领域和领域逻辑上,通过与领域专家的密切合作,不断提炼出领域模型。”
—— eric evans(ddd 之父,《领域驱动设计》作者)
核心思想:
- 软件系统的核心是业务领域(domain),而不是技术细节(如数据库、框架)。
- 开发者应与领域专家(业务人员)紧密协作,建立统一的“通用语言”(ubiquitous language)。
- 通过建模将复杂的业务逻辑转化为清晰的代码结构。
ddd 的三大核心概念
| 概念 | 说明 |
|---|---|
| ✅ 领域(domain) | 软件所要解决的现实世界问题范围,如“电商”、“银行信贷”、“物流”等。 |
| ✅ 模型(model) | 对领域内关键概念和规则的抽象,通常体现为代码中的类、方法、关系。 |
| ✅ 设计(design) | 如何组织代码结构,使模型在代码中清晰体现,便于维护和扩展。 |
ddd 的分层架构(经典四层)
+---------------------+ | 用户接口层(ui layer) | ← http、web、rpc 接口 +---------------------+ | 应用层(application layer) | ← 用例协调、事务控制 +---------------------+ | 领域层(domain layer) | ← 核心业务逻辑、实体、聚合、领域服务 +---------------------+ | 基础设施层(infrastructure layer)| ← 数据库、消息、外部服务调用 +---------------------+
⚠️ 依赖方向:上层依赖下层,但 ddd 推荐使用依赖倒置(如通过接口解耦)。
ddd 核心战术模式(战术设计)
这些是 ddd 中用于建模的具体“工具”:
| 概念 | 说明 |
|---|---|
| ✅ 实体(entity) | 有唯一标识的对象,生命周期中状态会变化。<br>如:user、order,用 id 区分。 |
| ✅ 值对象(value object) | 无唯一标识,只表示值或属性组合。<br>如:money、address,通过属性判断相等。 |
| ✅ 聚合(aggregate) | 一组关联对象的集合,有一个**聚合根(aggregate root)**作为入口。<br>如:order 是聚合根,包含 orderitem。 |
| ✅ 领域服务(domain service) | 处理跨多个实体的业务逻辑,本身无状态。<br>如:transferservice 转账服务。 |
| ✅ 工厂(factory) | 封装复杂对象的创建逻辑。 |
| ✅ 仓储(repository) | 提供聚合的持久化访问接口,屏蔽数据库细节。<br>如:orderrepository。 |
| ✅ 领域事件(domain event) | 表示领域中发生的事件,用于解耦。<br>如:ordercreatedevent。 |
示例:电商订单系统(java 代码片段)
// 值对象:金额
public class money {
private bigdecimal amount;
private string currency;
public money(bigdecimal amount, string currency) {
this.amount = amount;
this.currency = currency;
}
public money add(money other) {
if (!this.currency.equals(other.currency)) throw new illegalargumentexception();
return new money(this.amount.add(other.amount), currency);
}
}
// 实体:订单项
public class orderitem {
private long id;
private string productname;
private money price;
private int quantity;
}
// 聚合根:订单
public class order {
private long id;
private list<orderitem> items = new arraylist<>();
private money total;
private string status;
public void additem(orderitem item) {
this.items.add(item);
this.total = this.total.add(item.getprice().multiply(item.getquantity()));
}
public void confirm() {
if (this.status.equals("created")) {
this.status = "confirmed";
// 发布领域事件
domaineventpublisher.publish(new orderconfirmedevent(this.id));
}
}
}
// 领域服务
@service
public class orderservice {
public void cancelorder(order order) {
// 复杂业务逻辑
if (order.iscancelable()) {
order.setstatus("cancelled");
orderrepository.save(order);
}
}
}ddd 的优势
| 优点 | 说明 |
|---|---|
| ✅ 业务与代码高度一致 | 模型直接反映业务,便于沟通和维护。 |
| ✅ 高内聚、低耦合 | 聚合、领域服务等设计提升可维护性。 |
| ✅ 易于应对复杂业务 | 适合核心领域复杂的系统。 |
| ✅ 支持微服务拆分 | 每个“限界上下文”可对应一个微服务。 |
ddd 的适用场景
| 适合 | 不适合 |
|---|---|
| 业务复杂、核心逻辑多 | crud 简单系统(如后台管理) |
| 需要长期演进 | 短期项目、原型开发 |
| 有领域专家参与 | 团队缺乏业务理解 |
| 微服务架构 | 小型单体应用 |
ddd 与传统三层架构对比
| 维度 | 传统三层架构 | ddd 架构 |
|---|---|---|
| 关注点 | 技术分层(controller/service/dao) | 业务领域建模 |
| 业务逻辑位置 | 多在 service 层(贫血模型) | 在领域对象内部(充血模型) |
| 可维护性 | 复杂业务易混乱 | 更清晰、可扩展 |
| 学习成本 | 低 | 较高 |
总结
ddd 是一种“以业务为中心”的软件设计思想,它通过:
- 建立通用语言
- 提炼领域模型
- 使用聚合、实体、值对象、领域服务等模式
- 构建清晰、可维护、可扩展的系统
简单一句话:
不要只写 crud,要学会用代码表达业务!
推荐学习
- 书籍:《领域驱动设计:软件核心复杂性应对之道》—— eric evans
- 框架支持:spring boot + jpa 可很好地实现 ddd 分层
- 扩展:cqrs、事件溯源(event sourcing)、六边形架构(hexagonal architecture)
ddd 是中高级 java 工程师必备的设计能力,掌握后能显著提升系统设计水平。
ddd(领域驱动设计)是一种软件设计方法论,java中的ddd思想指的是将领域驱动设计的核心理念和实践应用于java项目开发中。
ddd的核心思想
1. 关注领域模型
核心目标:将业务逻辑集中在领域模型中,而不是分散在各个技术层中。
java
// 传统贫血模型 vs ddd充血模型
// ❌ 贫血模型(不推荐)
public class order {
private long id;
private bigdecimal amount;
// 只有getter/setter
}
public class orderservice {
public void calculatediscount(order order) {
// 业务逻辑在service中
}
}
// ✅ ddd充血模型(推荐)
public class order {
private long id;
private bigdecimal amount;
private list<orderitem> items;
// 业务逻辑在领域对象中
public bigdecimal calculatediscount() {
// 折扣计算逻辑
return this.amount.multiply(getdiscountrate());
}
private bigdecimal getdiscountrate() {
// 领域规则
if (amount.compareto(new bigdecimal("1000")) > 0) {
return new bigdecimal("0.9");
}
return bigdecimal.one;
}
}ddd的核心概念在java中的体现
1. 分层架构
java
// 典型ddd分层结构 ├── application/ // 应用层 - 用例协调 ├── domain/ // 领域层 - 业务核心 ├── infrastructure/ // 基础设施层 - 技术实现 └── interfaces/ // 接口层 - 对外暴露
2. 实体(entity)
java
public class order implements entity<order> {
private orderid id; // 值对象作为标识
private money totalamount;
private orderstatus status;
// 通过标识判断相等性
@override
public boolean equals(object obj) {
if (this == obj) return true;
if (obj == null || getclass() != obj.getclass()) return false;
order order = (order) obj;
return id.equals(order.id);
}
// 业务方法
public void cancel() {
if (!status.cancancel()) {
throw new illegalstateexception("订单无法取消");
}
this.status = orderstatus.cancelled;
}
}3. 值对象(value object)
java
public class money implements valueobject {
private final bigdecimal amount;
private final currency currency;
public money(bigdecimal amount, currency currency) {
this.amount = amount;
this.currency = currency;
}
// 值对象基于所有属性判断相等性
@override
public boolean equals(object obj) {
if (this == obj) return true;
if (obj == null || getclass() != obj.getclass()) return false;
money money = (money) obj;
return amount.compareto(money.amount) == 0 &&
currency.equals(money.currency);
}
// 不可变操作
public money add(money other) {
if (!currency.equals(other.currency)) {
throw new illegalargumentexception("货币类型不匹配");
}
return new money(amount.add(other.amount), currency);
}
}4. 聚合根(aggregate root)
java
public class order implements aggregateroot {
private orderid id;
private list<orderitem> items; // 内部实体
private customerid customerid;
// 聚合根负责维护完整性
public void additem(product product, int quantity) {
if (quantity <= 0) {
throw new illegalargumentexception("数量必须大于0");
}
orderitem newitem = new orderitem(product.getid(), quantity, product.getprice());
items.add(newitem);
recalculatetotal();
}
// 外部只能通过聚合根访问内部对象
public list<orderitem> getitems() {
return collections.unmodifiablelist(items);
}
}5. 领域服务(domain service)
java
public class ordercalculationservice {
// 处理不适合放在实体中的跨聚合业务逻辑
public discount calculatebestdiscount(order order, customer customer, list<promotion> promotions) {
// 复杂的折扣计算逻辑
return promotions.stream()
.filter(p -> p.isapplicable(order, customer))
.map(p -> p.calculatediscount(order))
.max(comparator.comparing(discount::getamount))
.orelse(discount.none);
}
}6. 仓储接口(repository)
java
// 领域层定义接口
public interface orderrepository {
order findbyid(orderid id);
void save(order order);
list<order> findbycustomerid(customerid customerid);
}
// 基础设施层实现
@repository
public class orderrepositoryimpl implements orderrepository {
@autowired
private orderjparepository jparepository;
@override
public order findbyid(orderid id) {
orderentity entity = jparepository.findbyid(id.getvalue())
.orelsethrow(() -> new ordernotfoundexception(id));
return ordermapper.todomain(entity);
}
}java中实现ddd的最佳实践
1. 包结构组织
java
com.example.ordermanagement
├── application
│ ├── command
│ ├── query
│ └── service
├── domain
│ ├── model
│ ├── service
│ ├── repository
│ └── exception
├── infrastructure
│ ├── persistence
│ ├── external
│ └── config
└── interfaces
├── rest
├── dto
└── mapper2. 使用特定注解标记
java
// 自定义注解明确ddd角色
@target(elementtype.type)
@retention(retentionpolicy.runtime)
public @interface domainentity {
}
@target(elementtype.type)
@retention(retentionpolicy.runtime)
public @interface domainservice {
}
@domainentity
public class order {
// 领域实体
}
@domainservice
public class ordervalidationservice {
// 领域服务
}ddd在java项目中的优势
业务复杂度管理:将复杂业务逻辑封装在领域模型中
代码可维护性:清晰的架构分层和职责分离
团队协作:统一的语言(ubiquitous language)
技术无关性:领域层不依赖具体技术实现
测试友好:领域对象可以独立测试
ddd特别适合业务复杂、需要长期维护的java企业级应用,能够有效应对业务变化和技术演进。
到此这篇关于java中的ddd思想指的是什么及在java中体现的文章就介绍到这了,更多相关java中ddd思想和体现内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论