浏览 5667 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2006-08-11
在整个DomainModel框架中,最基础的对象莫过于DomainObject。DomainObject既然是所有领域 对象的父类,就该体现最基础的特征。并且为其他层或某些方面提供一致的入口。 “有名万物之母”,这也是DomainObject中需要体现的。 DomainObject的名有很多,很多的原因是有很多关心它的参与者。 计算机使用的名--ID:必须,通常为64位的Integer。如果数据库是64位的CPU,据说这样定ID效率是最高的。 第三方和用户输入的名--Code:可选,String类型。尽管计算机知道了DomainObject,但用户却不知道,(用户登录系统就需要通过Code)第三方的开发人员也不知道。 用户期望看到的名--Name: 可选,String类型。对应于自然语言中的名。 用户期望看到的关于该对象的描述之名--Description:可选,String类型。这也需要最不重要的名了,对于该对象的备注,简要解释都可以放到这里。 有了名,我们就可以思考DomainObject了,基于“万物皆过程”的思考,表现过程的属性是需要加上的。于是 DomainObject有了{TimePeriod lifecycle}字段。lifecycle.start应该可以在某个构造函数中填入,当对象在业务上无效时可以填入lifecycle.end。DomainObject就“存活”于lifecycle之中。 当然你可以残酷一些,让DomainObject回归虚无,直接调用destroy方法,彻底删除它。 实际上持久化的DomainObject不过是反映了对象在lifecycle期间的当前快照,也就是说DomainObject存在很多快照, 我们可以使用{int version}来标识当前快照。 不知道什么时间,有人在DomainObject中放入了{int serialNumber},说是为了比较同类DomainObject的次序,我也说不清这是否站得住脚。 public abstract class DomainObject implements Comparable{ private Long id; private String code; private String name; private String description; private TimePeriod lifecycle; private int version; private int serialNumber; /** * 从持久层中重新构造DomainObject */ protected DomainObject(); { } /** * 业务上创建DomainObject */ protected DomainObject(String name, String code, int serialNumber, String description); { this.id = IdGenerator.getCurrent();.nextId(this);; this.version = 0; this.lifecycle = new TimePeriod();; this.name = name; this.code = code == null ? id.toString(); : code; this.serialNumber = serialNumber; this.description = description; } public void destroy(); { } @Override public int hashCode(); { assert id != null : this.getClass();.getName(); + " id为null"; return id.hashCode();; } @Override public boolean equals(Object obj); { if (!(obj instanceof DomainObject);); return false; DomainObject domainObj = (DomainObject); obj; return this.getId();.longValue(); == domainObj.getId();.longValue();; } public int compareTo(Object obj); { assert this.getClass(); == obj.getClass(); : "无在不同的DomainObject间比较"; DomainObject o = (DomainObject); obj; return this.serialNumber.compareTo(o.serialNumber);; } /** * 判断DomainObject是否已过期 */ public boolean isExpired(); { Calendar now = Calendar.getInstance();; if (now.compareTo(lifecycle.getEnd();); > 0); return true; else return false; } public TimePeriod getLifecycle(); { return (TimePeriod); lifecycle.clone();; } public void setEnd(Calendar end); { lifecycle.setEnd((Calendar); end.clone(););; } public void checkVersion(int version); { if (this.version.compareTo(version); != 0); throw new DataChangedByOthersException();; } } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-08-11
给DomainObject加lifecycle属性,有点意思,不过直觉概念会和工作流上的概念有点关联。
不知partech对此如何看。 int version我觉的倒是不要,如果强调这个version概念的话,那么业务上一定会要求保存所有version的history,那么利用这个history就可以了。 |
|
返回顶楼 | |
发表时间:2006-08-11
yimlin 写道 给DomainObject加lifecycle属性,有点意思,不过直觉概念会和工作流上的概念有点关联。
不知partech对此如何看。 int version我觉的倒是不要,如果强调这个version概念的话,那么业务上一定会要求保存所有version的history,那么利用这个history就可以了。 lifecycle和工作流没啥关系。 考虑一个Customer对象,他的lifecycle属性就表示它在系统中的存在时段。 那么如何知道一个Customer已经无效了呢?一种做法是在Customer加入注销标志,但是通过查看lifecycle具有额外的优点,不但知道Customer是否已注销,并且还知道什么时候注销的。 通过lifecycle来思考DomainObject,是一个较好的视角,比如前面判断DomainObject间的依赖关系,就可以通过考察lifecycle属性得到。 version的另一个作用,或者说主要作用,是为了防止在长事务中的并发修改问题。 关于记录DomainObject变更历史的问题,可以使用一个Aspect来处理,不用在业务层编写一行代码,或者说该特性是可以分离的一个方面。 |
|
返回顶楼 | |
发表时间:2006-08-11
partech 写道 yimlin 写道 给DomainObject加lifecycle属性,有点意思,不过直觉概念会和工作流上的概念有点关联。
不知partech对此如何看。 int version我觉的倒是不要,如果强调这个version概念的话,那么业务上一定会要求保存所有version的history,那么利用这个history就可以了。 lifecycle和工作流没啥关系。 考虑一个Customer对象,他的lifecycle属性就表示它在系统中的存在时段。 那么如何知道一个Customer已经无效了呢?一种做法是在Customer加入注销标志,但是通过查看lifecycle具有额外的优点,不但知道Customer是否已注销,并且还知道什么时候注销的。 通过lifecycle来思考DomainObject,是一个较好的视角,比如前面判断DomainObject间的依赖关系,就可以通过考察lifecycle属性得到。 version的另一个作用,或者说主要作用,是为了防止在长事务中的并发修改问题。 关于记录DomainObject变更历史的问题,可以使用一个Aspect来处理,不用在业务层编写一行代码,或者说该特性是可以分离的一个方面。 oh, 我从业务角度考虑,理解错了!原来两个都是技术处理的属性! |
|
返回顶楼 | |
发表时间:2006-08-16
partech 写道 考虑一个Customer对象,他的lifecycle属性就表示它在系统中的存在时段。 那么如何知道一个Customer已经无效了呢?一种做法是在Customer加入注销标志,但是通过查看lifecycle具有额外的优点,不但知道Customer是否已注销,并且还知道什么时候注销的。 通过lifecycle来思考DomainObject,是一个较好的视角,比如前面判断DomainObject间的依赖关系,就可以通过考察lifecycle属性得到。 如Customer这样的例子,生命周期不应是DomainObject的通用属性,我觉得应该以子类的方式提供。DomainObjectWithLifeCycle extends DomainObject implements LifeCycle? partech 写道 version的另一个作用,或者说主要作用,是为了防止在长事务中的并发修改问题。 关于记录DomainObject变更历史的问题,可以使用一个Aspect来处理,不用在业务层编写一行代码,或者说该特性是可以分离的一个方面。 是用Aspect来处理version自动变更的问题?在使用自动管理生命周期的ORM,象Hibernate的时候它是否在proxy里面维护自己的version?会画蛇添足么? |
|
返回顶楼 | |
发表时间:2006-08-16
Tin 写道 如Customer这样的例子,生命周期不应是DomainObject的通用属性,我觉得应该以子类的方式提供。DomainObjectWithLifeCycle extends DomainObject implements LifeCycle? why? Tin 写道 partech 写道 version的另一个作用,或者说主要作用,是为了防止在长事务中的并发修改问题。 关于记录DomainObject变更历史的问题,可以使用一个Aspect来处理,不用在业务层编写一行代码,或者说该特性是可以分离的一个方面。 是用Aspect来处理version自动变更的问题?在使用自动管理生命周期的ORM,象Hibernate的时候它是否在proxy里面维护自己的version?会画蛇添足么? 用Aspect来处理自动日志,可以是基于稽核的需要,或者需要关心活动中对象的变更历史。 |
|
返回顶楼 | |
发表时间:2006-08-17
partech 写道 Tin 写道 如Customer这样的例子,生命周期不应是DomainObject的通用属性,我觉得应该以子类的方式提供。DomainObjectWithLifeCycle extends DomainObject implements LifeCycle? why? 我是以为如果LifeCycle是一个业务需求,那么有些DomainObject会不关心LifeCycle,所以应该照顾到。而如果LifeCycle是版本管理或者在内存中管理时使用,那么则应该保留。 我是没太看明白而已。 |
|
返回顶楼 | |
发表时间:2006-08-17
Tin 写道 partech 写道 Tin 写道 如Customer这样的例子,生命周期不应是DomainObject的通用属性,我觉得应该以子类的方式提供。DomainObjectWithLifeCycle extends DomainObject implements LifeCycle? why? 我是以为如果LifeCycle是一个业务需求,那么有些DomainObject会不关心LifeCycle,所以应该照顾到。而如果LifeCycle是版本管理或者在内存中管理时使用,那么则应该保留。 我是没太看明白而已。 从需求上看,确实对于某些DomainObject来说,Lifecycle不在关心的范围之内,就如同不是所有的DomainObject都有自然语言的name。单继承结构的语言限制了,我们这种严格划分属性的需求。 对于DomainObject来说,除了ID其他的都可选,但正如不是所有的Object都需要toString,有时我们不得的不采用这种简明的方式来处理。 |
|
返回顶楼 | |
发表时间:2006-08-17
又发现一个可以加入DomainObject的候选方法checkInvariant(),检查该对象应当符合的不变式。
为了灵活,有时候,不是完全通过构造函数来构造完全有意义的DomianObject; 或者某些对象本身就是逐步构建起来的; 提交前,都需要检查它们的完整性。 调用时机可以考虑放在UnitOfWork提交之前。 |
|
返回顶楼 | |