DDD领域驱动设计详解-Java/Go/JS/Python实现

DDD 分层架构设计概述

领域驱动设计(Domain-Driven Design,简称 DDD)是一种软件架构方法,旨在通过分层和领域建模的方式来管理复杂业务逻辑。DDD 主要通过分层架构来组织代码,以实现高内聚、低耦合。

与传统的 MVC 架构相比,DDD 更侧重于抽象基础设施和领域层:复杂的业务规则和逻辑被集中放置在领域层,而强大的基础设施则为领域层提供有力支持。这种设计理念非常适合构建复杂的企业级应用,使系统更具弹性和可持续发展性。

查看源码: github.com/microwind/d...

DDD 结构图形示例

sql 复制代码
+--------------------+
|     用户界面层       |
|   User Interface   |
+--------------------+
          |
          v
+--------------------+
|   应用服务层         |
|  Application Layer |
+--------------------+
          |
          v
+--------------------+
|       领域层        |
|    Domain Layer    |
+--------------------+
          |
          v
+----------------------+
|   基础设施层           |
| Infrastructure Layer |
+----------------------+

各层职责

  • 用户界面(UI)层:处理用户输入与展示信息。
  • 应用服务层:负责应用层流程逻辑,协调领域层的操作。
  • 领域层:实现核心业务逻辑,包括实体、值对象、聚合、领域服务等。
  • 基础设施层:提供数据库、外部 API、消息队列等技术支持。

DDD 分层架构与 MVX 分层架构的对比

特性 MVX(MVC/MVP/MVVM) DDD(领域驱动设计)
主要目标 分离 UI、业务逻辑和数据 解决复杂领域建模与业务逻辑
关注点 UI 驱动,适用于前端开发 领域驱动,适用于复杂业务系统
层次 3 层(Model、View、X) 4 层(UI、应用、领域、基础设施)
适用场景 前端框架、强交互应用 企业级系统、复杂业务领域

DDD 的应用场景

  • 企业级系统,如电商平台、ERP、银行系统。
  • 业务逻辑复杂,需要清晰的领域建模。
  • 多个系统交互,涉及数据库、外部 API、消息队列等。
  • 团队协作开发,需要业务人员和开发人员紧密合作。

DDD 的例子(C、Java、JavaScript、Go、Python)

C 语言实现 DDD

C 语言不支持 OOP,但可以用结构体和函数模块化实现 DDD。

c 复制代码
/* 用户界面层(UI Layer)*/
// ui.c
#include <stdio.h>
#include "application.h"

int main() {
    OrderService service;
    init_service(&service);
    
    create_order(&service, "1001", "Alice", 250.5);
    Order order = get_order(&service, "1001");

    printf("Retrieved Order: %s, %s, %.2f\n", order.id, order.customer_name, order.amount);
    return 0;
}

/* 应用服务层(Application Layer)*/
// order_service.c
#include <string.h>
#include "application.h"

void init_service(OrderService *service) {
    init_repository(&service->repo);
}

void create_order(OrderService *service, const char *id, const char *name, float amount) {
    Order order;
    strcpy(order.id, id);
    strcpy(order.customer_name, name);
    order.amount = amount;
    save_order(&service->repo, order);
}

Order get_order(OrderService *service, const char *id) {
    return find_order(&service->repo, id);
}

/* 领域层(Domain Layer)*/
// order.h
#ifndef DOMAIN_H
#define DOMAIN_H

typedef struct {
    char id[10];
    char customer_name[50];
    float amount;
} Order;

#endif

/* 基础设施层(Infrastructure Layer)*/
// order_repository.c
#include <stdio.h>
#include <string.h>
#include "infrastructure.h"

void init_repository(OrderRepository *repo) {
    repo->count = 0;
}

void save_order(OrderRepository *repo, Order order) {
    repo->orders[repo->count++] = order;
}

Order find_order(OrderRepository *repo, const char *id) {
    for (int i = 0; i < repo->count; i++) {
        if (strcmp(repo->orders[i].id, id) == 0) {
            return repo->orders[i];
        }
    }
    Order empty = { "", "", 0 };
    return empty;
}

Java 语言实现 DDD

java 复制代码
/* 用户界面层(UI Layer)*/
// UI.java
public class UI {
    public static void main(String[] args) {
        OrderService service = new OrderService();
        service.createOrder("1001", "Alice", 250.5);
        Order order = service.getOrder("1001");

        System.out.println("Retrieved Order: " + order);
    }
}

/* 应用服务层(Application Layer)*/
// OrderService.java
class OrderService {
    private OrderRepository repository = new OrderRepository();

    public void createOrder(String id, String name, double amount) {
        Order order = new Order(id, name, amount);
        repository.save(order);
    }

    public Order getOrder(String id) {
        return repository.findById(id);
    }
}

/* 领域层(Domain Layer)*/
// Order.java
class Order {
    String id, customerName;
    double amount;

    public Order(String id, String name, double amount) {
        this.id = id;
        this.customerName = name;
        this.amount = amount;
    }

    public String toString() {
        return id + ", " + customerName + ", " + amount;
    }
}

/* 基础设施层(Infrastructure Layer)*/
// OrderRepository.java
import java.util.*;

class OrderRepository {
    private Map<String, Order> db = new HashMap<>();

    public void save(Order order) {
        db.put(order.id, order);
    }

    public Order findById(String id) {
        return db.get(id);
    }
}

Go 语言实现 DDD

go 复制代码
/* 用户界面层(UI Layer)*/
// ui.go
func main() {
	repo := NewOrderRepository()
	service := NewOrderService(repo)

	service.CreateOrder("1001", "Alice", 250.5)
	order := service.GetOrder("1001")

	fmt.Println("Retrieved Order:", order)
}

/* 应用服务层(Application Layer)*/
// order_service.go
type OrderService struct {
	repo *OrderRepository
}

func NewOrderService(repo *OrderRepository) *OrderService {
	return &OrderService{repo: repo}
}

func (s *OrderService) CreateOrder(id, name string, amount float64) {
	order := Order{ID: id, CustomerName: name, Amount: amount}
	s.repo.Save(order)
}

func (s *OrderService) GetOrder(id string) Order {
	return s.repo.FindById(id)
}

/* 领域层(Domain Layer)*/
// order.go
type Order struct {
	ID           string
	CustomerName string
	Amount       float64
}

/* 基础设施层(Infrastructure Layer)*/
// order_repository.go
type OrderRepository struct {
	data map[string]Order
}

func NewOrderRepository() *OrderRepository {
	return &OrderRepository{data: make(map[string]Order)}
}

func (r *OrderRepository) Save(order Order) {
	r.data[order.ID] = order
}

func (r *OrderRepository) FindById(id string) Order {
	return r.data[id]
}

Python 语言实现 DDD

py 复制代码
# 用户界面层(UI Layer)
# ui.py
from application import OrderService

service = OrderService()
service.create_order("1001", "Alice", 250.5)
order = service.get_order("1001")

print(f"Retrieved Order: {order}")


# 应用服务层(Application Layer)
# order_service.py
from domain import Order
from infrastructure import OrderRepository

class OrderService:
    def __init__(self):
        self.repository = OrderRepository()

    def create_order(self, order_id, name, amount):
        order = Order(order_id, name, amount)
        self.repository.save(order)

    def get_order(self, order_id):
        return self.repository.get(order_id)


# 领域层(Domain Layer)
# order.py
class Order:
    def __init__(self, order_id, customer_name, amount):
        self.order_id = order_id
        self.customer_name = customer_name
        self.amount = amount

    def __str__(self):
        return f"{self.order_id}, {self.customer_name}, {self.amount}"

# 基础设施层(Infrastructure Layer)
# order_repository.py
class OrderRepository:
    def __init__(self):
        self.db = {}

    def save(self, order):
        self.db[order.order_id] = order

    def get(self, order_id):
        return self.db.get(order_id, None)

JavaScript (Node.js版) 实现 DDD

javascript 复制代码
/* 用户界面层(UI Layer)*/
// UI.js
const OrderService = require("./OrderService");

const service = new OrderService();
service.createOrder("1001", "Alice", 250.5);
console.log("Retrieved Order:", service.getOrder("1001"));

/* 应用服务层(Application Layer)*/
// OrderService.js
const Order = require("./Order");
const OrderRepository = require("./OrderRepository");

class OrderService {
    constructor() {
        this.repository = new OrderRepository();
    }

    createOrder(id, name, amount) {
        const order = new Order(id, name, amount);
        this.repository.save(order);
    }

    getOrder(id) {
        return this.repository.get(id);
    }
}

module.exports = OrderService;

/* 领域层(Domain Layer)*/
// Order.js
class Order {
    constructor(id, customerName, amount) {
        this.id = id;
        this.customerName = customerName;
        this.amount = amount;
    }
}

module.exports = Order;

/* 基础设施层(Infrastructure Layer)*/
// OrderRepository.js
class OrderRepository {
    constructor() {
        this.db = {};
    }

    save(order) {
        this.db[order.id] = order;
    }

    get(id) {
        return this.db[id] || null;
    }
}

module.exports = OrderRepository;

JavaScript (前端版) 实现 DDD

javascript 复制代码
/* 用户界面层(UI Layer)*/
// UI.js
class View {
    constructor(selector) {
        this.$ele = document.querySelector(selector);
        this.template = `
            <div>
                <h2>订单管理</h2>
                <form id="orderForm">
                    <input type="text" id="orderId" placeholder="订单 ID" required>
                    <input type="text" id="customerName" placeholder="客户名称" required>
                    <input type="number" id="amount" placeholder="金额" required>
                    <button type="submit">提交订单</button>
                </form>
                <ul id="orderList"></ul>
            </div>
        `;
    }

    init() {
        this.$ele.innerHTML = this.template;
        this.bindEvents();
    }

    bindEvents() {
        const $form = this.$ele.querySelector("#orderForm");
        $form.addEventListener("submit", async (event) => {
            event.preventDefault();
            const id = this.$ele.querySelector("#orderId").value;
            const name = this.$ele.querySelector("#customerName").value;
            const amount = parseFloat(this.$ele.querySelector("#amount").value);

            await orderService.createOrder(id, name, amount);
            this.updateOrderList();
        });
    }

    async updateOrderList() {
        const orders = await orderService.getAllOrders();
        const $orderList = this.$ele.querySelector("#orderList");
        $orderList.innerHTML = orders
            .map(order => `<li>ID: ${order.id}, 客户: ${order.customerName}, 金额: ${order.amount}</li>`)
            .join("");
    }
}

// **初始化 UI**
const app = new View("#app");
app.init();
app.updateOrderList();


/* 应用服务层(Application Layer)*/
// OrderService.js
class OrderService {
    constructor(repository) {
        this.repository = repository;
    }

    async createOrder(id, name, amount) {
        const order = new Order(id, name, amount);
        await this.repository.save(order);
    }

    async getAllOrders() {
        return await this.repository.getAll();
    }
}

const orderService = new OrderService(new OrderRepository());

/* 领域层(Domain Layer)*/
// Order.js
class Order {
    constructor(id, customerName, amount) {
        this.id = id;
        this.customerName = customerName;
        this.amount = amount;
    }
}


/* 基础设施层(Infrastructure Layer)*/
// 前端应用里面对于数据操作主要是调用接口,此处可以改为OrderAPI.js
// OrderRepository.js
class OrderRepository {
    constructor() {
        this.apiUrl = "http://localhost:3000/api/orders"; // 后端API地址
    }

    async save(order) {
        await fetch(this.apiUrl, {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(order)
        });
    }

    async getAll() {
        const response = await fetch(this.apiUrl);
        return response.json();
    }
}

总结

  • DDD 适用于复杂业务系统,强调领域建模和高内聚低耦合。
  • MVX 适用于 UI 结构清晰的前端应用,重点在于 UI 与业务逻辑的分离。
  • 不同语言都可以实现 DDD,关键是遵循分层架构原则。

最后

  • 要用DDD吗? 不是每个项目都适合DDD,是否采用DDD应当根据项目的实际情况来。
  • 什么叫适合? 就是开发团队开发和维护起来最清晰、最靠谱、最轻松就是最适合的。

源码

DDD本质上是一种代码组织策略,旨在帮助开发者更高效地理解、构建和维护系统。不同编程语言特点不同,但都能基于DDD架构构造出清晰、易维护、可扩展的代码。

相关推荐
excel1 分钟前
webpack 核心编译器 第一节
前端
多多*10 分钟前
Java 双端队列实战 实现滑动窗口 用LinkedList的基类双端队列Deque实现 洛谷[P1886]
java·开发语言·数据结构·算法·cocoa
大怪v12 分钟前
前端佬们!塌房了!用过Element-Plus的进来~
前端·javascript·element
拉不动的猪23 分钟前
electron的主进程与渲染进程之间的通信
前端·javascript·面试
网络风云25 分钟前
Flask(三)路由与视图函数
后端·python·flask
Asthenia041237 分钟前
Java 线程的状态转换 / 操作系统线程状态转换 / 线程上下文切换详解 / 如何避免线程切换
后端
江沉晚呤时44 分钟前
深入解析外观模式(Facade Pattern)及其应用 C#
java·数据库·windows·后端·microsoft·c#·.netcore
uhakadotcom44 分钟前
云原生数据仓库对比:Snowflake、Databricks与阿里云MaxCompute
后端·面试·github
软件技术NINI1 小时前
html css 网页制作成品——HTML+CSS非遗文化扎染网页设计(5页)附源码
前端·css·html
fangcaojushi1 小时前
npm常用的命令
前端·npm·node.js