#08.贫血模式与充血模式
贫血模型 :是指领域模型里只有setter和getter方法,本身不包含业务逻辑,所有的业务逻辑放在业务逻辑层(Service/Logic)层。
充血模型 :领域模型除了setter和getter方法外,还有业务逻辑处理和持久化,业务逻辑层只负责部分业务逻辑以及事务、权限等。
在OOP中,一个领域模型(Domain Object)只包含属性的setter和getter是不合理的【贫血模型】,它应该还具备一定的行为,例如Person类可以save()等, 既有属性,同时也有行为(业务逻辑)【充血模型】。
每种模型都有它的优缺点以及适用的场合:
贫血模型的好处:
- 每个贫血模型只包含属性的setter和getter方法,只包含对象的状态,职责单一,解耦程度高。
- 适合软件外包和大规模软件团队协作,每个编程个体只需要负责单一的业务逻辑模块编写,不会互相影响。
我们在Spring时,基本都是使用的贫血模型。
贫血模型的坏处:
- 只包含对象的状态而没有行为。行为的逻辑需要提升到业务逻辑层完成,例如一个User类对应一个UserService来完成其行为。如果模型间需要互相协作, 那么就需要提升到Service层协作,当业务逻辑多且复杂情况下,业务逻辑层会变得膨胀而臃肿,复用率低。
- 对象协作需要依赖外部容器的组装(Service层互相依赖),通常会借助IOC容器等完成(Spring适用场合)。
充血模型的好处:
- 模型既有属性也有行为,符合面向对象编程,表达能力强(例如person.speak()),适合业务逻辑负责的场合,复用程度高。
- 不用依赖外部容器的组装。
充血模型的坏处:
- 不利于大规模团队分工协作(贫血模式可以将行为提到业务逻辑层处理)。
- 随着业务逻辑变动,领域模型会频繁变动(贫血模式很可能只需要修改业务逻辑层即可)。
贫血模型只拥有属性而没有对象该有的行为,只能用来保存对象的状态,从根本上违背了面向对象的原则。 而将业务逻辑提升到Service层处理是赤裸裸的 面向事务编程 的方式。Spring基本这种方式。
充血模型符合面向对象编程,代码实现会更加优雅。
这里讨论对比那么多,并不是要得出结论谁上下高低,本人更推崇在合适的场合使用合适的手段,不要为了设计而设计,为了模式而模式。
贫血模型也好,充血模式也罢,在适合的场合使用适当的方式才是王道,哪怕领域模型都木有,直接使用Map<String,String>也不赖。