我有一个聚合根Entity
,它会在请求时进行一些处理。如果在该处理期间满足条件,则必须初始化SubEntity
。问题是SubEntity
还有一个子实体Status
,它必须使用来自数据库的起始值进行初始化。
我试图密切关注SOLID和DDD原则,但我对此很新。我现在使用它的方式是使用工厂,但它看起来不对我,因为我不喜欢让这个工厂由消费者类服务(为了遵循DIP ),因为这是该实体内域逻辑的一部分。
我这样做了吗?这是设计此类的正确方法吗?我有哪些替代方案?
public class Entity
{
public virtual SubEntity SubEntity { get; private set; }
public void Process(int someData, ISubEntityFactory subEntityFactory)
{
if (SomeConditionIsMet)
{
SubEntity = subEntityFactory.Create(this);
}
}
}
public class SubEntity
{
public SubEntity(Entity entity, Status status)
{
Entity = entity;
Status = status;
}
public virtual Entity Entity { get; private set; }
public virtual Status Status { get; private set; }
}
public class Status
{
public const int StartingId = 1;
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<SubEntity> SubEntity { get; private set; }
}
public class SubEntityFactory : ISubEntityFactory
{
// property and constructor omitted
public SubEntity Create(Entity entity)
{
var status = UnitOfWork.StatusRepository.GetByID(Status.StartingId);
return new SubEntity(entity, status);
}
}
根据Dmi的最佳答案,我决定收到一个initialStatus
变量作为Process
方法的参数,因此我的域名未与数据库耦合。然后,我验证initialStatus
以确保其id
匹配Status.StartingId
。在那之后,我甚至不再需要工厂了,它看起来更清洁了。
public class Entity
{
public virtual SubEntity SubEntity { get; private set; }
public void Process(int someData, Status initialStatus)
{
ValidateInitialStatus(initialStatus);
if (SomeConditionIsMet)
{
SubEntity = new SubEntity(this, initialStatus);
}
}
private void ValidateInitialStatus(Status initialStatus)
{
if (initialStatus == null)
{
throw new ArgumentNullException("initialStatus");
}
if (initialStatus.Id != Status.StartingId)
{
throw new ArgumentException("Initial status is invalid");
}
}
}
public class SubEntity
{
public SubEntity(Entity entity, Status status)
{
Entity = entity;
Status = status;
}
public virtual Entity Entity { get; private set; }
public virtual Status Status { get; private set; }
}
public class Status
{
public const int StartingId = 1;
public int Id { get; set; }
public string Description { get; set; }
public virtual ICollection<SubEntity> SubEntity { get; private set; }
}
答案 0 :(得分:3)
你工厂里的UnitOfWork.StatusRepository.GetByID(Status.StartingId)
似乎很可疑。尽量避免将工厂连接到存储库(虽然反过来也可以,例如在重组期间使用工厂)。
一个干净的解决方案如下:
public class Entity
{
private readonly ISubEntityFactory _subEntityFactory;
public Entity(ISubEntityFactory subEntityFactory) {
_subEntityFactory = subEntityFactory;
}
public void Process(int someData, Status initialStatus)
{
if (SomeConditionIsMet)
{
SubEntity = _subEntityFactory.Create(this, initialStatus);
}
}
}
这导致调用应用服务必须检索initialStatus
。我想你想要避免这种情况,但它比将数据库与数据库耦合更清晰(我会不惜一切代价避免)。
如果可以,请将initialStatus
重新设计为值对象。我不知道你的情况是否可行,但它会使设计更加健壮。
另外,不要将subEntityFactory
作为参数传递。工厂是一种特殊的服务,所以它应该注入施工人员而不是传递给他们。这使Entity
对工厂的依赖性明确,这很好。
请注意,在实体中具有服务依赖性通常会得出结论:最好通过工厂创建或重构实体。这样,工厂可以在构建时提供特定实体所需的所有服务。永远记住对象构造是一个实现细节,客户端不需要知道它就可以使用对象。