当前位置: 首页 > news >正文

DDD领域驱动中瘦模型与富态模型的核心区别

🧠 DDD领域驱动中瘦模型与富态模型的核心区别

引用

  1. 最肯忘卻古人詩 最不屑一顧是相思
  2. 春又來看紅豆開 竟不見有情人去采

🧬 1. 核心定义与哲学思想

🏁 瘦模型(Anemic Model)

【定义】 只包含数据字段和基础getter/setter方法的“哑对象”,业务逻辑外置于服务层
【哲学】 源自面向过程思想,强调“数据与行为分离”,类似于C语言结构体。
C++结构示例 📐:

// 纯数据载体
class CustomerAnemic {
public:std::string name() const { return name_; }void setName(const std::string& name) { name_ = name; }double balance() const { return balance_; }void setBalance(double balance) { balance_ = balance; } private:std::string name_;double balance_ = 0.0;
};// 业务逻辑在服务类中
class CustomerService {
public:void deductBalance(CustomerAnemic& customer, double amount) {if (amount > customer.balance())throw std::runtime_error("Insufficient balance");customer.setBalance(customer.balance() - amount);}
};
🏁 富态模型(Rich Model)

【定义】 数据与行为高度内聚的领域对象,封装业务规则和状态变更逻辑。
【哲学】 遵循面向对象设计原则,核心是“高内聚、低耦合”和“封装不变性”。
C++实现 📐:

class CustomerRich {
public:CustomerRich(const std::string& name, double balance) : name_(name), balance_(balance) {}void deductBalance(double amount) {if (amount > balance_) throw std::runtime_error("Insufficient balance");balance_ -= amount;addTransaction("DEDUCT", amount); // 内部状态联动}void addTransaction(const std::string& type, double amount) {transactions_.push_back({type, amount});}private:std::string name_;double balance_;std::vector<std::pair<std::string, double>> transactions_;
};

🔍 2. 本质区别可视化对比

维度🪫 瘦模型🔋 富态模型
业务逻辑位置❗ 位于Service层✅ 封装在领域对象内部
领域对象角色📦 数据容器(类似DTO)⚙️ 自治的行为主体
状态变更控制⚠️ 外部服务类直接修改状态✅ 仅通过对象方法内部修改
业务规则表达力📉 规则散布在服务类中📈 通过对象方法自然展现领域规则
与DDD的契合度❌ 违反DDD聚合根设计原则✅ 完美实现DDD聚合根概念
数据一致性边界🔓 跨对象逻辑需事务管理🔒 聚合根内天然一致性保证
⭐ 关键区别示意图

在这里插入图片描述


🎯 3. 应用场景深度分析

💡 瘦模型适用场景
  1. 简单CRUD系统:如后台管理系统,业务规则少
  2. 需极简架构场景:微服务间数据传输(DTO模式)
  3. 重度依赖框架的遗留系统:如使用Hibernate且需脱离数据库逻辑
  4. 高性能要求场景:避免对象方法调用开销
💡 富态模型适用场景
  1. 复杂业务核心域:如电商交易系统、风控引擎
  2. 领域逻辑频繁变更:封装变化点降低维护成本
  3. 需强一致性保证:如银行账户扣款+流水记录原子操作
  4. 业务规则易用性优先:降低Service层复杂度

⚖️ 4. 优劣势深度剖析

🛡️ 富态模型核心优势
优势原理说明DDD设计影响
领域自洽性💎 对象自含完整性校验逻辑(如 deductBalance()实现聚合根的自治性
高可维护性🔧 业务变更仅需修改领域对象契合限界上下文(Bounded Context)
表达领域语言🗣️ 方法名如 placeOrder() 直接映射领域事件强化统一语言(Ubiquitous Language)
防贫血设计🩸 根治Martin Fowler提出的贫血模型问题符合DDD战术设计原则
并发控制优化🔒 聚合根内提供乐观锁实现点简化事务边界管理
⚠️ 富态模型潜在局限
  1. 对象膨胀风险 ➜ 方法过多时破坏单一职责原则
  2. 框架适配困难 ➜ ORM框架需支持复杂领域逻辑
  3. 学习曲线陡峭 ➜ 需深入理解DDD和OOP设计思想
  4. 性能开销 ➜ 领域对象内聚导致单次操作耗时增加

🧩 5. 实践案例:电商订单系统的对比

🛒 订单处理逻辑实现对比

瘦模型实现(业务逻辑外置):

// OrderService.cpp
void OrderService::placeOrder(OrderAnemic& order) {if (order.items().empty()) throw InvalidOrder();double total = 0;for (auto& item : order.items()) {total += item.price() * item.quantity();}order.setTotal(total);  // 外部修改状态if (!PaymentService::pay(order.user(), total)) throw PaymentFailed();InventoryService::deductItems(order.items()); // 跨服务调用order.setStatus(PLACED); // 状态变更分散
}

富态模型实现(业务逻辑内聚):

// OrderRich.cpp
void OrderRich::placeOrder() {if (items_.empty()) throw InvalidOrder();total_ = calculateTotal(); // 内部方法处理status_.attemptTransition(PLACING); // 状态机模式auto payment = std::make_shared<Payment>(user_, total_);payment->execute();  // 领域事件驱动if (payment->isSuccess()) {items_.deductInventory(); // 领域内聚合协作status_.setStatus(PLACED);} else {status_.setStatus(FAILED);throw PaymentFailed();}
}
🚦 关键差异点说明
  1. 状态变更:富态模型中status_由内部状态机控制
  2. 业务规则:总价计算封装在calculateTotal()私有方法
  3. 事务边界:聚合根OrderRich保证订单操作原子性
  4. 领域协作:直接调用ItemList子实体的业务方法

🧭 6. 混合应用策略建议

  1. 分层架构平衡 ⚖️
    简单操作
    UI层
    应用层
    领域层-Rich Model
    基础设施层
    基础服务层-Anemic
  2. 场景化选择原则
    • 核心域 ➜ 100%富态模型
    • 支撑子域 ➜ 瘦模型加速开发
    • 通用子域 ➜ 混合设计
  3. 技术适配方案 🧰
    • ORM框架使用EF Core或Hibernate支持聚合根
    • 复杂逻辑采用领域服务补充

🧪 7. 富态模型设计进阶技巧

  1. 状态模式应用
class OrderStatus {
public:virtual void ship(OrderRich& order) = 0;// 其他状态方法...
};class PlacedStatus : public OrderStatus {
public:void ship(OrderRich& order) override {order.notifyShipped();order.setStatus(std::make_unique<ShippedStatus>());}
};
  1. 领域事件驱动
class OrderRich {
public:void addDomainEvent(std::unique_ptr<DomainEvent> event) {domainEvents_.push_back(std::move(event));}void publishEvents() {for (auto& event : domainEvents_) DomainEventPublisher::publish(*event);domainEvents_.clear();}
private:std::vector<std::unique_ptr<DomainEvent>> domainEvents_;
};

🔚 8. 结论

瘦模型作为简单的数据传输结构,在非核心领域可提供快速实现方案。而富态模型作为DDD的战术核心,通过内聚领域逻辑,在构建复杂业务系统时提供:
✅ 更清晰的业务语义表达
✅ 更强的模型一致性保证
✅ 更高的内聚度和可维护性


💎 决策矩阵
在这里插入图片描述

建议:在战略层面识别核心域,富态模型投入产出比可达10:1;在战术实施中优先保证聚合根的完整性设计加粗样式

http://www.dtcms.com/a/302296.html

相关文章:

  • 设计模式(二十四)行为型:访问者模式详解
  • PostgreSQL日志配置全解析:从基础设置到进阶策略
  • 用 Python 获取电脑电池电量的各种案例
  • Python数据处理基础(学习笔记分享)
  • 【Spring WebFlux】 三、响应式流规范与实战
  • 科技赋能成长 脑力启迪未来
  • JVM 内存共享区域详解
  • Uniswap V2 成功上线 PolkaVM:Polkadot Hub 的里程碑时刻
  • 5190 - 提高:DFS序和欧拉序:树上操作(区域修改1)
  • 28天0基础前端工程师完成Flask接口编写
  • Ethereum:Geth运维实战,geth export与geth import命令的实用性深度评估
  • 【C++】手搓一个STL风格的vector容器
  • 【华为机试】210. 课程表 II
  • Kernel PWN 入门(二)
  • 【深度学习优化算法】10:Adam算法
  • Mybatis_4
  • 设计模式十二:门面模式 (FaçadePattern)
  • Kafka——请求是怎么被处理的?
  • 6.2 总线事务和定时 (答案见原书 P295)
  • 疏老师-python训练营-Day28类的定义和方法
  • 【LeetCode 热题 100】35. 搜索插入位置——二分查找(闭区间)
  • 区块链分叉原理与代码仿真
  • leetcode 2044. 统计按位或能得到最大值的子集数目 中等
  • 主要分布于内侧内嗅皮层的层Ⅲ的网格-速度联合细胞(Grid × Speed Conjunctive Cells)对NLP中的深层语义分析的积极影响和启示
  • 热斑漏检率↓78%!陌讯多模态算法在无人机光伏巡检的轻量化实践
  • 问题大全【1】
  • 【深度解析】R语言与作物模型(以DSSAT模型为例)融合应用
  • 散点图(散点矩阵)相关介绍
  • 【计算机科学与应用】基于多域变换的视频水印嵌入算法研究
  • 电脑出现英文字母开不了机怎么办 原因与修复方法