我在我当前的项目中越来越多地采用DDD /洋葱架构。 我仍然不清楚的许多事情之一是应该有多少封装。 用一个具体的例子更容易解释。
示例
namespace MyProject.Model
{
public class ComplexEntity
{
private int _id;
public int Id { get {return _id;} }
public ValueObjectA ValueA {get; set;}
public bool IsBool {get; set;}
public ComplexEntity(ValueObjectA a, bool isBool)
{
// Do some validation first
ValueA = a;
ValueB = b;
IsBool = isBool;
}
}
public class ValueObjectA
{
public bool IsBoolA {get; private set;}
public bool IsBoolB {get; private set;}
public ValueObjectA(bool a, bool b)
{
IsBoolA = a;
IsBoolB = b;
}
}
public Interface IComplextEntityFactory
{
// Option 1
ComplexEntity Create(
ValueObjectA a,
bool IsBool);
// Option 2
ComplexEntity Create(
bool valueABool a,
bool valueBBool b,
bool isBool);
}
}
问题
对于实体的工厂,你呢,
我倾向于选择2,但我似乎无法找到支持文献。
修改1
说实话,我仍然不清楚。集合根源怎么样?
当我的实体引用其他实体时,例如下方。
IComplexEntityFactory
,ILessComplexEntityFactory
吗?或者只是创建LessComplexEntity的IComplexEntityAggregateFactory
并实例化ComplexEntity? AggregateFactory的方法签名是什么?会是(ValueObject a, ValueObject b)
还是(ValueObject value, LessCompelxEntity entity)
公共类ComplexEntity { private readonly int _id; public int Id {get {return _id;}}
public ValueObject Value {get; set;}
public LessComplexEntity Entity {get; set;}
public ComplexEntity(int id, ValueObject value, LessComplexEntity entity)
{
}
}
公共类LessComplexEntity { private readonly int _id; public int Id {get {return _id;}} public ValueObject Value {get;组;} public LessComplexEntity(int id,ValuObject value) { } }
答案 0 :(得分:3)
我会选择选项1。
向每个人明确表示您需要使用ValueObjectA来构建ComplexEntity。当你看到某处使用的方法时,更易读,更少抓头。
如果ValueObjectA发生更改,则必须仅在一个位置(工厂的调用者)修改代码,而不是更改Create()的签名+调整工厂内的值对象创建。
工厂的Create()方法的参数较少,冗长,可读性更强。
在单元测试中,它为您提供了更多选项,以便能够注入您想要的ValueObjectA。如果将ValueObjectA的创建完全隐藏在工厂内,那么在测试方面你可以做的很多。
<强> [编辑] 强>
目前尚不清楚您的聚集根和工厂的真正问题是什么,但您不应该将检索/补充现有对象的责任与创建对象的责任混为一谈。
作为一般规则,工厂的工作是从较小的部分组装一个新对象(无论它们是原始类型,值对象,实体......)
工厂应该提供所有这些部件,检索或从某个地方补充水分不是它的责任。您可以将其留给工厂的来电者。它将使工厂更cohesive并与更少的类(存储库等)相结合
答案 1 :(得分:1)
我更喜欢选项#1,因为它会减少工厂方法所需的参数数量。但我的建议是,当有问题的聚合需要创建策略时,才使用工厂。
在你的一条评论中,你说:
“..然后我不明白工厂的好处。那么它所做的只是调用ComplexEntity的构造函数而不是创建构成它的所有子组件。”
工厂的工作是通过查看传递给它的数据来决定如何实例化聚合。根据我的经验,需要这种情况的常见情况是使用了继承/多态。例如,假设您有一个抽象的Account类,有两个子类:SavingsAccount&amp; CurrentAccount。工厂的工作是根据一些数据决定实例化哪一个。
工厂的另一个潜在好处是你的表现力如何。如果聚合可以以多种方式实例化(即不同的参数),那么这可以用工厂上的方法名称比重载的构造函数更好地表达。
正如我所说,除非出于上述原因之一,我的建议是不为每个集合创建工厂。否则,正如您所指出的那样,它只是一行调用构造函数,并传递相同的参数。