我目前正在尝试DDD并阅读埃文斯的书。我已经到达了一个模型,该模型的根是Student。现在我需要(或能够区分)RegisteredStudent和EnrolledStudent(继承RegisteredStudent)。我不知道如何在DDD中处理继承。
2个继承的类应该在聚合中吗?如果是这样,它们是否也被认为是聚合根,因为它们的身份与根相同(只有添加属性)?如果没有,我如何从其他实体访问它们?
或者我应该不使用继承?为什么呢?
而且,如果您的聚合中的实体不是根,但是您需要在外部继承实体,该怎么办?你应该怎么做呢?
答案 0 :(得分:11)
您需要问自己的是,RegisteredStudent和EnrolledStudent是不同的概念。他们不是学生,而是处于不同的状态吗?
一般来说,你应该赞成合成而不是继承。
这是我要做的一个例子。 (请注意,这仅仅是我的例子,我不知道域名,所以它不是一个明确的解决方案。)
您可以拥有一个Student类,它是您的聚合根,然后是几个不同的州类:Registered
和Enrolled
。这样您就不需要在学生上公开这些状态类,但您可以在学生上公开方法。一个小例子(在c#中):
class Student
{
State _currentState;
void Enroll()
{
if(!_currentState is Registered)
throw new InvalidOperationException("Cannot enroll student who is not registered");
this._currentState = new Enrolled();
}
void Register(string name)
{
this._currentState = new Registered(name);
}
}
class StudentState{}
class Enrolled : StudentState
{}
class Registered : StudentState
{
public Registered(string name)
{
Name = name;
}
public string Name {get; private set;}
}
这是一个简单的状态设计模式应用程序,你可以将其中的更多部分外部化并构建一个完整的状态机,但我会把它留给你。 (它也直接输入到SO编辑器中,因此可能存在语法错误)
评论后编辑:
是否需要公开State-property取决于上下文。一般来说,我建议不要这样做,因为你暴露了学生的内部。例如,公开一个名为CanEnroll
的方法会更好。这样,您可以更改状态模式的内部实现,而不会影响任何客户端。
至于问题3,没有用例很难说。但是,这里有一些指导原则: