文章摘要(AI生成)
业务场景用户登录时可以有如下方法提供注册功能:public void register(String name, String phone);public void register(String name, String phone, String idCard);出现问题:在字段拓展时,外部使用
业务场景
用户登录时可以有如下方法提供注册功能:
public void register(String name, String phone);
public void register(String name, String phone, String idCard);
出现问题:
- 在字段拓展时,外部使用者调用此方法无法知道具体参数顺序,可能导致传参问题
- 校验逻辑在多个校验方法中重复编写,参数校验和业务异常混在一个方法中
所以针对这种问题,我们要进行修改,以求达到:接口语义明确,拓展性强。参数校验复用,且与业务逻辑判断解耦.
我们的解决方法是:创建一个用户的领域对象,这个对象包含对应的name
,phone
,idCard
,以及对应的校验逻辑。
public class User {
private String name;
private String phone;
private String idCard;
public User(String name, String phone, String idCard) {
if(checkName(name)
|| checkPhone(phone)
||checkIdCard(idCard)){
throw new RuntimeException("参数校验失败");
}
this.name = name;
this.phone = phone;
this.idCard = idCard;
}
private boolean checkName(String name){
//校验逻辑...
return true;
}
private boolean checkPhone(String phone){
//校验逻辑...
return true;
}
private boolean checkIdCard(String idCard){
//校验逻辑...
return true;
}
对应的注册方法不再做参数校验,那么这个抽出来的User就是我们DDD中所说的领域原型(Domain Primitive)。
这里我们需要知道传统POJO和领域对象的区别了:
- 传统POJO属于贫血模型
- 领域对象属于充血模型
下面是两者的具体差异:
充血模型和贫血模型
贫血模型-POJO
是指领域对象里只有get和set方法,或者包含少量的CRUD方法,所有的业务逻辑都不包含在内而是放在业务逻辑层。
优点是系统的层次结构清楚,各层之间单向依赖
缺点是不够面向对象,领域对象只是作为保存状态或者传递状态使用,所以就说只有数据没有行为的对象不是真正的对象
充血模型-DP
Domain Primitive
是一个在特定领域里,拥有精准定义的、可自我验证的、拥有行为的 Value Object
。大多业务逻辑和持久化放在Domain Object
里面,业务层只是简单封装部分业务逻辑以及控制事务、权限等
优点是面向对象,业务层符合单一职责,不像在贫血模型里面那样包含所有的业务逻辑太过沉重
缺点是如何划分业务逻辑很难界定。
针对领域原型的实现,有三个主要原则:
- 让隐性的概念显像化
- 让隐性的上下文显像化
- 封装多对象行为
Entity 与 Value Object
当采用面向对象的设计方法对系统进行建模时,我们需要做的是从业务需求中找到那些关键的「业务对象」,而这些业务对象也是 DDD 中 Entity 与 Value Object 的基础。我们先来看一下 Entity 与 Value Object 有什么区别。
Entity 应该是我们在日常分析过程中最熟悉的部分,它也是业务逻辑的核心体现。它应该具备以下的特性:
- Entity应该具唯一的「标识」
- 相比Entity所拥有的数据属性,我们更关注的是它的唯一「标识」
与之对应的 Value Object 顾名思义,关注的是数据,因为它并没有唯一标识:
- 没有唯一标识
- 我们更加关注于它的数据属性
DP与ENTITY
DP是一切模型、方法、架构的基础,是指在特定领域、拥有精准定义、可以自我验证、拥有行为的对象,可以认为是领域的最小组成部分
DP: 抽象并封装自检和一些隐性属性的计算逻辑,且这些逻辑是无状态的
Entity: 抽象并封装单对象有状态的逻辑
两者最显著的区别在于针对对象的逻辑是否有状态。什么叫状态?总结是“该对象是否存在生命周期”,“程序是否需要追踪该对象的变化事件”。比如上述示例中,我们不关注用户的注册状态,登录状态等信息,此时的用户就是一个DP,如果我们需要关注用户的注册状态和登录状态了,此时用户就变为一个entity了。
评论区