首先应该认识到,是对象就有生命周期。这一点无论在面向对象语言还是在领域驱动设计中都适用。在领域驱动设计中,模型对象生命周期可以简要地用下图表示:
通过上图可以看到,对象通过工厂从无到有创建,创建后处于活动状态,此时可以参与领域层的业务处理;对象通过仓储实现持久化(也就是我们常说的“保存”)和重建(也就是我们常说的“读取”)。内存中的对象通过析构而消亡,处于持久化状态的对象则通过仓储进行撤销(也就是我们常说的“删除”)。整个状态转换过程非常清晰。
现在引出了管理模型对象生命周期的两种角色:工厂和仓储。同时也需要注意的是,工厂和仓储的操作都是基于聚合根(Aggregate Root)的,而不仅仅是针对实体的。关于仓储,内容会比较多,我在下一节单独讲述。在本节介绍一下工厂在.NET实体框架(EntityFramework)中的实现。
在打开了.NET实体框架自动生成的Entity Data Model Source Code文件后,我们发现,.NET实体框架为每一个实体添加了一个工厂方法,该方法包含了一系列原始数据类型和值类型的参数。比如,我们案例中的 Customer实体就有如下的代码:
Customer Factory
/// <summary>
/// Create a new Customer object.
/// </summary>
/// <param name="id">Initial value of the Id property.</param>
/// <param name="name">Initial value of the Name property.</param>
/// <param name="billingAddress">Initial value of the BillingAddress property.</param>
/// <param name="deliveryAddress">Initial value of the DeliveryAddress property.</param>
/// <param name="loginName">Initial value of the LoginName property.</param>
/// <param name="loginPassword">Initial value of the LoginPassword property.</param>
/// <param name="dayOfBirth">Initial value of the DayOfBirth property.</param>
public static Customer CreateCustomer(global::System.Int32 id, Name name, Address billingAddress,
Address deliveryAddress, global::System.String loginName,
global::System.String loginPassword, global::System.DateTime dayOfBirth)
{
Customer customer = new Customer();
customer.Id = id;
customer.Name = StructuralObject.VerifyComplexObjectIsNotNull(name, "Name");
customer.BillingAddress = StructuralObject.VerifyComplexObjectIsNotNull(billingAddress, "BillingAddress");
customer.DeliveryAddress = StructuralObject.VerifyComplexObjectIsNotNull(deliveryAddress, "DeliveryAddress");
customer.LoginName = loginName;
customer.LoginPassword = loginPassword;
customer.DayOfBirth = dayOfBirth;
return customer;
}