贫血模型和充血模型以及最佳实践
贫血模型和充血模型对于接触后端的人说可能更熟悉
贫血模型
先画一张图
这张图展现的就是表现层常用的逻辑,即查询逻辑。而且是一个贫血模型
我们有一个User对象,伪代码如下
1 | public class User |
总共有五个属性,但是在表现层的界面中,只需要显示三个属性:姓名、年龄、ID
我们在表现层使用GetUserById返回的是一整个User对象,这种数据流向模型叫做贫血模型
IUserModel的伪代码
1 | public interface IUserModel : IModel |
我们可以看到Model中GetUserById
返回的是User
,最后显示的时候需要在表现层进行一层筛选
充血模型
也是一张图
我们不返回完整的User了,而是定义一个新的UserInfo用来返回信息,这些信息和表现层UserInfoViewController一一对应
这个就是典型的充血模型
UserInfo
伪代码
1 | public class UserInfo |
IUserModel
伪代码
1 | public interface IUserModel : IModel |
充血模型就是表现层需要哪些数据,就刚好返回哪些数据,不多不少。
充血模型比贫血模型多做了一些工作,并且也多了一些性能消耗。
但是在越大型的项目中充血模型的好处就越明显。
因为充血模型,可以让我们的代码更精确地描述业务,会提高代码的可读性,比如表现层需要展示的是UserInfo,那么就返回UserInfo对象,而不是所有的表现层都直接获取User而分不开各个表现层要的是什么。贫血模型,会让我们的数据趋于混乱。
Framwork基于充血模型的查询建议
在Model内部直接给出查询方法
引人IUserInfoSystem
引入IUserInfoSystem
用于封装IUserModel
的查询
UserModel该返回User就返回User,而表现层需要的UserInfo需要在UserInfoSystem里过滤出来
这种方式其实是更标准一些的,很多服务器的四层架构都是这么实现的,这里的系统层也即是服务器端的应用层
使用Command加事件
在Command内部获取UserModel
,并调用GetUserById
,并且在Command内部将User转化为UserInfo,发送GetUserInfoByIdSucceedEvent(UserInfo userinfo)
事件,我们在表现层监听此事件即可。
建议使用第二种、第三种查询方式,因为在很多情况下,数据所设计的Model不只有一个,很多需要组合查询,使用Command或者定义一个专门用来查询的System就能更好地访问多个Model,分层就是为了减少表现层的代码量。
充血模型是指在项目中流通的对象,不是在Model中定义的用于存储的对象(上述例子中User属于存储对象,UserInfo属于流通对象)流通。充血模型则是存储对象在流通。
查询是充血模型的主要用例之一,其他还有传参等也是需要充血模型的理念