用代理模式解决胀血模型的弊端
用代理模式解决胀血模型的弊端
Aaron
本文是对《领域模型方面的管理》(作者 Mats Helander,译者 王丽娟)一文的读后总结,有兴趣的朋友可以找原文来看。
一、问题的由来
领域模型有4种:失血模型、贫血模型、充血模型、胀血模型。
其中胀血模型又称为胖领域模型,它的弊端是:
1.混杂了与领域模式无关的功能,导致领域模型代码被基础架构代码淹没了,无法突出重点,模型不“干净”,需要花力气区分领域模型代码与基础架构代码,增加维护难度。
比如模型的状态,都是和领域模型的业务字段混杂在一起。
Class Employee : BaseModel
{
Private bool isDirty;
Public bool IsDirty
{
Get
{
Return isDirty;
}
}
//领域模型的字段。
Private string name;
Public string Name
{
Get
{
Return name;
}
Set
{
If (name != value)
{
Name = value;
//状态并非领域模型的范畴,它属于基础架构的功能。
base.isDirty = true;
}
}
}
}
2.有些领域模型不需要的基础架构功能,也被强制插进领域模型的类中,浪费资源。
比如持久化、模型状态、缓存初始值都属于常见的基础架构,按胀血模型的做法,这些功能是放在基类BaseModel里的,然后领域模型继承基类之后,同时拥有了持久化和状态的功能。
但有些领域模式是不需要延迟加载,或者不需要缓存初始值的,在胀血模型下,这些功能没办法丢弃。
3.领域模型和基础架构代码混杂还会产生一个很不好的后果:因为基础架构总是依赖ORM框架实现的,而每个ORM的基础架构实现都不一样,所以你的领域模型就被绑死在某一个ORM框架上了,无法跨ORM重用。
二、问题的解决
简单地分离领域模型和基础架构代码,虽然可以解决问题,但会变成失血模型或者贫血模型,这并不是我们想要的。
可以使用代理模式解决,以下类图:
其中ILazyLaoder的方法在每个用到的Proxy类中都要重复写一次,这样很烦琐。可以写一个LazyLoader的辅助类LazyLoadHelper,使用组合模式,让Proxy类和辅助类合并起来工作,这样既可以减少重复代码,而且便于用代码自动生成器来生成Proxy类。