赋予领域模型生命力:充血模型在现代软件架构中的崛起(架构篇)_封装
充血模型是一种软件设计方法,它将业务逻辑和决策能力赋予领域对象本身,而不是将它们放置在外部的业务逻辑层或服务层中。这种方法强调领域对象的完整性和自足性,使得每个领域对象都能够独立地执行其业务规则。

肖哥弹架构 跟大家“弹弹” 代码设计技巧,需要代码关注

欢迎 点赞,点赞,点赞。

关注公号Solomon肖哥弹架构获取更多精彩内容

历史热点文章

2. 充血模型设计图:

充血模型的设计哲学是让领域对象拥有自己的行为和状态管理,从而使得系统更加模块化、灵活和可维护。充血模型中的状态管理指的是领域对象负责维护和控制自己的状态信息,确保状态的完整性和一致性。领域对象不仅包含业务逻辑,还包含确保对象状态有效性的逻辑,本章最后有详细介绍。
赋予领域模型生命力:充血模型在现代软件架构中的崛起(架构篇)_设计规则_02

  • Order 类代表订单,包含订单编号、用户、商品项列表,以及下单、添加商品项和计算总价的方法。
  • Customer 类代表用户,包含用户编号、名字和姓氏,以及获取全名的方法。
  • OrderItem 类代表订单中的商品项,包含产品编号、数量、价格,以及计算商品总价的方法。
  • OrderService 类代表订单服务,负责处理订单。
  • Product 类代表产品,包含产品编号、名称和价格。
  • InventoryService 类代表库存服务,负责检查产品的可用性。
3. 充血模型解决什么:

充血模型解决了贫血模型中领域对象过于简单、缺乏表达力的问题,以及业务逻辑集中在服务层导致的服务层臃肿和难以维护的问题。

4. 充血模型特点:
  • 高内聚性:领域对象包含所有相关的业务逻辑和状态。
  • 低耦合度:领域对象之间的交互简单,依赖性低。
  • 易于维护:业务逻辑封装在领域对象内,便于理解和修改。
5. 充血模型缺点:
  • 可能的复杂性:领域对象可能变得复杂,需要更多的设计和实现工作。
  • 过度封装:在某些情况下,可能会导致过度封装,使得领域对象难以理解和使用。
6. 充血模型使用场景:

当系统需要高度模块化和灵活性时,或者当业务逻辑紧密依赖于领域对象的状态和行为时,应考虑使用充血模型。

7. 充血模型案例
7.1 电商平台的订单处理系统案例

电商平台的订单处理系统,该系统需要处理订单和用户信息。

重构前(贫血模型)

    public class Order {
        private String orderId;
        private double totalAmount;
        // 仅包含基本的getter和setter方法
    }

    public class OrderService {
        public void processOrder(Order order) {
            // 订单处理逻辑,如计算总价、应用折扣等
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

分析问题:

  1. 业务逻辑分散
    • 在实现前,业务逻辑可能分散在多个服务类或外部管理类中,导致领域模型缺乏行为。
  2. 领域模型贫血
    • 领域对象可能仅包含数据和访问器,没有实现任何业务逻辑,这使得它们过于简单且不完整。
  3. 高耦合度
    • 服务类和领域对象之间可能存在高耦合度,服务类对领域对象的内部状态有深入了解和依赖。
  4. 可维护性差
    • 由于业务逻辑的分散和高耦合,系统可能难以维护和扩展,任何更改都可能影响到多个部分。
  5. 测试复杂性
    • 测试可能依赖于复杂的设置和模拟,特别是如果业务逻辑依赖于外部服务类的状态。

重构后(充血模型)

    public class Order {
        private String orderId;
        private double totalAmount;
        private List<OrderItem> items;

        public void addItem(OrderItem item) {
            items.add(item);
            totalAmount += item.getPrice();
        }

        public void applyDiscount(double discount) {
            totalAmount -= discount;
        }

        public boolean placeOrder() {
            // 订单放置逻辑,可能包括验证、库存检查等
            return true;
        }
    }

    // 领域服务,协调领域对象之间的交互
    public class OrderService {
        public void processOrder(Order order) {
            order.placeOrder();
            // 其他协调逻辑
        }
    }
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.

解决的问题:

  1. 业务逻辑集中
    • 充血模型将业务逻辑封装在领域对象内部,使得每个对象都具有自足的行为。
  2. 领域模型丰富
    • 领域对象不再只是数据容器,而是拥有自己的行为和业务规则,提高了模型的表达力。
  3. 降低耦合度
    • 领域对象与外部服务的耦合度降低,因为它们独立于业务逻辑的实现。
  4. 提高可维护性
    • 由于业务逻辑封装在领域对象内,系统的可维护性得到提高,更改和扩展更加容易。
  5. 简化测试
    • 领域对象的独立性使得编写单元测试变得更加简单,因为测试可以集中在单个对象的行为上。
  6. 增强封装性
    • 充血模型通过封装业务逻辑,提高了系统的封装性,减少了外部对内部状态的依赖。
  7. 更好的业务规则控制
    • 领域对象可以更好地控制业务规则的执行,确保业务逻辑的正确性和一致性。
8. 参考开源框架:

许多现代应用程序和框架,如Domain-Driven Design (DDD) 框架,鼓励使用充血模型来设计领域对象。

9. 总结:

充血模型通过将业务逻辑封装在领域对象内部,提高了系统的模块化和灵活性。这种方法使得领域对象更加自足,易于理解和维护。虽然可能会导致领域对象的复杂性增加,但它为构建可维护、可扩展的软件系统提供了坚实的基础。遵循充血模型有助于创建出更加健壮、灵活和易于维护的软件系统。