分层架构之模型,DO,DTO之间的关系
按照一个请求实体进入系统后,它在分层架构的各层之间传递的顺序,可以分为,请求命令层,领域模型层,业务实现层。那么各层实体如何创建?存在的形态?各层级之间实体的传递方式是什么样的呢?
请求命令层
这一层如果进行了CQRS命令改造,那么命令可以分为读请求Query,写请求Command,事件请求(写命令)Event。这一层的价值在于传递命令或请求,不做任何其他的事情,是纯的pojo,有get/set方法。
如创建用户命令:
public class CreateUserCmd {
private String name;
private Integer phone;
// get/set 方法
}
请求命令层的实体定义在COLA框架中client层。client层的价值在于能够为客户端(web,wap,作为jar包)提供各种现成的纯实体,方便客户端调用。
请求命令层的实例产生于adaptor层,即对应到web请求,或者消息实体,adaptor层依赖于client层,然后在adaptor层传递到app层。整个过程我们不会主动调用请求命令的set方法,它的价值在于传递客户端的信息,预留set方法主要是为了满足框架的实体转换需求。
领域模型层
领域模型层是所有业务逻辑实现的地方,每个模型要包含其所有的逻辑操作。抛开逻辑实现,我们只关注领域模型实体如何生成。
- 构造函数
最基本的方式是我们给领域实体暴露出的构造函数。
比如
public class User implement Entity {
private String name;
private Integer phone;
public User(String name, Integer phone) {
this.name = name;
this.phone = phone;
}
public void initDefaultPermission() {
// 初始化用户权限
}
}
请求从adaptor层进入app层再到领域层,这时我们借助请求命令里的信息,如name,phone字段,去创建我们的领域模型实例new User(name.phone)
,再用创建出的user去执行业务方法user.initDefaultPermission()
。
- 领域工厂
对于复杂的模型,可以用工厂方法来构建。
- 构建者
对于业务字段多,字段之间有约束的实体,用构建者模式会更加方便。
注意,领域实体没有set方法。它的一切实例化都要用它暴露出去的方法,要么是构造方法,要么是工厂方法,绝对不可以用new对象,然后set的方式,以免造成模型一致性的破坏。
业务实现层
纯POJO,主要用作持久化层或RPC之间的传递数据的作用。
从领域实体到它的转化,主要靠set方法。
UserDO userDo = new UserDO();
userDO.setName(name);
userDO.setPhone(phone);
可以用mapstruct等工具简化这个过程。当然有的领域实体和实现层之间的字段也会有差异,比如领域层定义的是enum,而实现层的DO是一个String,这种就需要手动转化一下。主要写一写胶水语句,没有实现上的难度。
而从业务实现层到领域实体的转化,靠领域实体的构造器,工厂或构建者,也就是上面说过的三种方式。
总结
其实除了领域层的领域实体要用领域暴露的方法来构建,其他的都是纯POJO。主要目的是为了保证领域模型的逻辑一致性。不要破坏这种规则。