java中的DDD思想指的是什么及在Java中的體現(xiàn)詳解
前言
Java 中的 DDD 指的是 領(lǐng)域驅(qū)動設(shè)計(Domain-Driven Design),它是一種軟件開發(fā)方法論,強(qiáng)調(diào)以業(yè)務(wù)領(lǐng)域為核心來設(shè)計和構(gòu)建復(fù)雜系統(tǒng)。DDD 并不是一種框架或技術(shù),而是一種設(shè)計思想和架構(gòu)理念,特別適用于業(yè)務(wù)邏輯復(fù)雜、核心領(lǐng)域價值高的系統(tǒng)(如金融、電商、ERP 等)。
什么是 DDD(Domain-Driven Design)?
“把軟件的焦點放在核心領(lǐng)域和領(lǐng)域邏輯上,通過與領(lǐng)域?qū)<业拿芮泻献鳎粩嗵釤挸鲱I(lǐng)域模型。”
—— Eric Evans(DDD 之父,《領(lǐng)域驅(qū)動設(shè)計》作者)
核心思想:
- 軟件系統(tǒng)的核心是業(yè)務(wù)領(lǐng)域(Domain),而不是技術(shù)細(xì)節(jié)(如數(shù)據(jù)庫、框架)。
- 開發(fā)者應(yīng)與領(lǐng)域?qū)<?/strong>(業(yè)務(wù)人員)緊密協(xié)作,建立統(tǒng)一的“通用語言”(Ubiquitous Language)。
- 通過建模將復(fù)雜的業(yè)務(wù)邏輯轉(zhuǎn)化為清晰的代碼結(jié)構(gòu)。
DDD 的三大核心概念
| 概念 | 說明 |
|---|---|
| ? 領(lǐng)域(Domain) | 軟件所要解決的現(xiàn)實世界問題范圍,如“電商”、“銀行信貸”、“物流”等。 |
| ? 模型(Model) | 對領(lǐng)域內(nèi)關(guān)鍵概念和規(guī)則的抽象,通常體現(xiàn)為代碼中的類、方法、關(guān)系。 |
| ? 設(shè)計(Design) | 如何組織代碼結(jié)構(gòu),使模型在代碼中清晰體現(xiàn),便于維護(hù)和擴(kuò)展。 |
DDD 的分層架構(gòu)(經(jīng)典四層)
+---------------------+ | 用戶接口層(UI Layer) | ← HTTP、Web、RPC 接口 +---------------------+ | 應(yīng)用層(Application Layer) | ← 用例協(xié)調(diào)、事務(wù)控制 +---------------------+ | 領(lǐng)域?qū)樱―omain Layer) | ← 核心業(yè)務(wù)邏輯、實體、聚合、領(lǐng)域服務(wù) +---------------------+ | 基礎(chǔ)設(shè)施層(Infrastructure Layer)| ← 數(shù)據(jù)庫、消息、外部服務(wù)調(diào)用 +---------------------+
?? 依賴方向:上層依賴下層,但 DDD 推薦使用依賴倒置(如通過接口解耦)。
DDD 核心戰(zhàn)術(shù)模式(戰(zhàn)術(shù)設(shè)計)
這些是 DDD 中用于建模的具體“工具”:
| 概念 | 說明 |
|---|---|
| ? 實體(Entity) | 有唯一標(biāo)識的對象,生命周期中狀態(tài)會變化。<br>如:User、Order,用 id 區(qū)分。 |
| ? 值對象(Value Object) | 無唯一標(biāo)識,只表示值或?qū)傩越M合。<br>如:Money、Address,通過屬性判斷相等。 |
| ? 聚合(Aggregate) | 一組關(guān)聯(lián)對象的集合,有一個**聚合根(Aggregate Root)**作為入口。<br>如:Order 是聚合根,包含 OrderItem。 |
| ? 領(lǐng)域服務(wù)(Domain Service) | 處理跨多個實體的業(yè)務(wù)邏輯,本身無狀態(tài)。<br>如:TransferService 轉(zhuǎn)賬服務(wù)。 |
| ? 工廠(Factory) | 封裝復(fù)雜對象的創(chuàng)建邏輯。 |
| ? 倉儲(Repository) | 提供聚合的持久化訪問接口,屏蔽數(shù)據(jù)庫細(xì)節(jié)。<br>如:OrderRepository。 |
| ? 領(lǐng)域事件(Domain Event) | 表示領(lǐng)域中發(fā)生的事件,用于解耦。<br>如:OrderCreatedEvent。 |
示例:電商訂單系統(tǒng)(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";
// 發(fā)布領(lǐng)域事件
DomainEventPublisher.publish(new OrderConfirmedEvent(this.id));
}
}
}
// 領(lǐng)域服務(wù)
@Service
public class OrderService {
public void cancelOrder(Order order) {
// 復(fù)雜業(yè)務(wù)邏輯
if (order.isCancelable()) {
order.setStatus("CANCELLED");
orderRepository.save(order);
}
}
}DDD 的優(yōu)勢
| 優(yōu)點 | 說明 |
|---|---|
| ? 業(yè)務(wù)與代碼高度一致 | 模型直接反映業(yè)務(wù),便于溝通和維護(hù)。 |
| ? 高內(nèi)聚、低耦合 | 聚合、領(lǐng)域服務(wù)等設(shè)計提升可維護(hù)性。 |
| ? 易于應(yīng)對復(fù)雜業(yè)務(wù) | 適合核心領(lǐng)域復(fù)雜的系統(tǒng)。 |
| ? 支持微服務(wù)拆分 | 每個“限界上下文”可對應(yīng)一個微服務(wù)。 |
DDD 的適用場景
| 適合 | 不適合 |
|---|---|
| 業(yè)務(wù)復(fù)雜、核心邏輯多 | CRUD 簡單系統(tǒng)(如后臺管理) |
| 需要長期演進(jìn) | 短期項目、原型開發(fā) |
| 有領(lǐng)域?qū)<覅⑴c | 團(tuán)隊缺乏業(yè)務(wù)理解 |
| 微服務(wù)架構(gòu) | 小型單體應(yīng)用 |
DDD 與傳統(tǒng)三層架構(gòu)對比
| 維度 | 傳統(tǒng)三層架構(gòu) | DDD 架構(gòu) |
|---|---|---|
| 關(guān)注點 | 技術(shù)分層(Controller/Service/DAO) | 業(yè)務(wù)領(lǐng)域建模 |
| 業(yè)務(wù)邏輯位置 | 多在 Service 層(貧血模型) | 在領(lǐng)域?qū)ο髢?nèi)部(充血模型) |
| 可維護(hù)性 | 復(fù)雜業(yè)務(wù)易混亂 | 更清晰、可擴(kuò)展 |
| 學(xué)習(xí)成本 | 低 | 較高 |
總結(jié)
DDD 是一種“以業(yè)務(wù)為中心”的軟件設(shè)計思想,它通過:
- 建立通用語言
- 提煉領(lǐng)域模型
- 使用聚合、實體、值對象、領(lǐng)域服務(wù)等模式
- 構(gòu)建清晰、可維護(hù)、可擴(kuò)展的系統(tǒng)
簡單一句話:
不要只寫 CRUD,要學(xué)會用代碼表達(dá)業(yè)務(wù)!
推薦學(xué)習(xí)
- 書籍:《領(lǐng)域驅(qū)動設(shè)計:軟件核心復(fù)雜性應(yīng)對之道》—— Eric Evans
- 框架支持:Spring Boot + JPA 可很好地實現(xiàn) DDD 分層
- 擴(kuò)展:CQRS、事件溯源(Event Sourcing)、六邊形架構(gòu)(Hexagonal Architecture)
DDD 是中高級 Java 工程師必備的設(shè)計能力,掌握后能顯著提升系統(tǒng)設(shè)計水平。
DDD(領(lǐng)域驅(qū)動設(shè)計)是一種軟件設(shè)計方法論,Java中的DDD思想指的是將領(lǐng)域驅(qū)動設(shè)計的核心理念和實踐應(yīng)用于Java項目開發(fā)中。
DDD的核心思想
1. 關(guān)注領(lǐng)域模型
核心目標(biāo):將業(yè)務(wù)邏輯集中在領(lǐng)域模型中,而不是分散在各個技術(shù)層中。
java
// 傳統(tǒng)貧血模型 vs DDD充血模型
// ? 貧血模型(不推薦)
public class Order {
private Long id;
private BigDecimal amount;
// 只有g(shù)etter/setter
}
public class OrderService {
public void calculateDiscount(Order order) {
// 業(yè)務(wù)邏輯在Service中
}
}
// ? DDD充血模型(推薦)
public class Order {
private Long id;
private BigDecimal amount;
private List<OrderItem> items;
// 業(yè)務(wù)邏輯在領(lǐng)域?qū)ο笾?
public BigDecimal calculateDiscount() {
// 折扣計算邏輯
return this.amount.multiply(getDiscountRate());
}
private BigDecimal getDiscountRate() {
// 領(lǐng)域規(guī)則
if (amount.compareTo(new BigDecimal("1000")) > 0) {
return new BigDecimal("0.9");
}
return BigDecimal.ONE;
}
}DDD的核心概念在Java中的體現(xiàn)
1. 分層架構(gòu)
java
// 典型DDD分層結(jié)構(gòu) ├── application/ // 應(yīng)用層 - 用例協(xié)調(diào) ├── domain/ // 領(lǐng)域?qū)?- 業(yè)務(wù)核心 ├── infrastructure/ // 基礎(chǔ)設(shè)施層 - 技術(shù)實現(xiàn) └── interfaces/ // 接口層 - 對外暴露
2. 實體(Entity)
java
public class Order implements Entity<Order> {
private OrderId id; // 值對象作為標(biāo)識
private Money totalAmount;
private OrderStatus status;
// 通過標(biāo)識判斷相等性
@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);
}
// 業(yè)務(wù)方法
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; // 內(nèi)部實體
private CustomerId customerId;
// 聚合根負(fù)責(zé)維護(hù)完整性
public void addItem(Product product, int quantity) {
if (quantity <= 0) {
throw new IllegalArgumentException("數(shù)量必須大于0");
}
OrderItem newItem = new OrderItem(product.getId(), quantity, product.getPrice());
items.add(newItem);
recalculateTotal();
}
// 外部只能通過聚合根訪問內(nèi)部對象
public List<OrderItem> getItems() {
return Collections.unmodifiableList(items);
}
}5. 領(lǐng)域服務(wù)(Domain Service)
java
public class OrderCalculationService {
// 處理不適合放在實體中的跨聚合業(yè)務(wù)邏輯
public Discount calculateBestDiscount(Order order, Customer customer, List<Promotion> promotions) {
// 復(fù)雜的折扣計算邏輯
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
// 領(lǐng)域?qū)佣x接口
public interface OrderRepository {
Order findById(OrderId id);
void save(Order order);
List<Order> findByCustomerId(CustomerId customerId);
}
// 基礎(chǔ)設(shè)施層實現(xiàn)
@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中實現(xiàn)DDD的最佳實踐
1. 包結(jié)構(gòu)組織
java
com.example.ordermanagement
├── application
│ ├── command
│ ├── query
│ └── service
├── domain
│ ├── model
│ ├── service
│ ├── repository
│ └── exception
├── infrastructure
│ ├── persistence
│ ├── external
│ └── config
└── interfaces
├── rest
├── dto
└── mapper2. 使用特定注解標(biāo)記
java
// 自定義注解明確DDD角色
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DomainEntity {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DomainService {
}
@DomainEntity
public class Order {
// 領(lǐng)域?qū)嶓w
}
@DomainService
public class OrderValidationService {
// 領(lǐng)域服務(wù)
}DDD在Java項目中的優(yōu)勢
業(yè)務(wù)復(fù)雜度管理:將復(fù)雜業(yè)務(wù)邏輯封裝在領(lǐng)域模型中
代碼可維護(hù)性:清晰的架構(gòu)分層和職責(zé)分離
團(tuán)隊協(xié)作:統(tǒng)一的語言(Ubiquitous Language)
技術(shù)無關(guān)性:領(lǐng)域?qū)硬灰蕾嚲唧w技術(shù)實現(xiàn)
測試友好:領(lǐng)域?qū)ο罂梢元毩y試
DDD特別適合業(yè)務(wù)復(fù)雜、需要長期維護(hù)的Java企業(yè)級應(yīng)用,能夠有效應(yīng)對業(yè)務(wù)變化和技術(shù)演進(jìn)。
到此這篇關(guān)于java中的DDD思想指的是什么及在Java中體現(xiàn)的文章就介紹到這了,更多相關(guān)java中DDD思想和體現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring的xml文件打開沒有namespace等操作選項的解決方案
這篇文章主要介紹了spring的xml文件打開沒有namespace等操作選項的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09
Springboot集成RabbitMQ死信隊列的實現(xiàn)
在大多數(shù)的MQ中間件中,都有死信隊列的概念。本文主要介紹了Springboot集成RabbitMQ死信隊列的實現(xiàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-09-09
詳解Android系統(tǒng)中的root權(quán)限獲得原理
這篇文章主要介紹了詳解Android系統(tǒng)中的Root權(quán)限獲得原理,安卓基于Linux,所以原理也相當(dāng)于Linux中的root用戶,需要的朋友可以參考下2015-08-08
打開.properties中文顯示unicode編碼問題以及解決
這篇文章主要介紹了打開.properties中文顯示unicode編碼問題以及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
劍指Offer之Java算法習(xí)題精講數(shù)組與列表的查找及字符串轉(zhuǎn)換
跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化2022-03-03

