如何建模一个可以是几种类型(在几种状态下)的域对象?

时间:2013-12-15 17:58:03

标签: oop design-patterns architecture domain-driven-design

示例:拥有一个可以拥有1个或更多不同类型的宠物(猫,狗,大象,海豹等)的人。

我会考虑制作一个聚合体,它将Human作为root(将petCollection作为Pet的引用)和另一个将Pet作为root的聚合(使用cat,dog,elephant,eagle作为此聚合的子元素)。

问题是每种宠物类型可能有不同的行为(例如:密封可以swin()但它不会飞()/鹰可以飞()但它不会游泳())。因此,州或战略模式似乎并不正确。如果一个人不知道它的类型,怎么能告诉宠物对象跑()?使用状态/策略模式,对象需要具有类似的行为。执行if / else(对于多态检查对象类型的情况)再次检查,似乎不是一个合适的设计。

我应该如何设计这个域或哪些模式可以帮助我?

3 个答案:

答案 0 :(得分:2)

一般来说,如果某事(仅/永远)某事,你应该使用继承。

如果 某事,你应该使用一个接口。

如果扮演某个角色(例如,法律方扮演客户和/或供应商的角色),您应该使用Composition。

所以Seal继承了Animal并实现了Swim,Bark

Dog继承Animal并实现Run,Bark

如果你想要你的动物游泳,那么要么迭代它们检查它们是否实施Swim然后调用swim(),或者在迭代它之前过滤该集合以获得实施Swim的动物。

答案 1 :(得分:1)

聚合根和继承通常不是一个好主意。

您可能希望避免一个Aggregate拥有其他聚合的集合。 Aggregate(以及其中之一)的概念是它代表事务边界,因此理想情况下,在这种结构中应该不需要。

但是,当一个Aggregate具有其他聚合ID的集合时,这是正常的。

答案 2 :(得分:1)

我不确定这里有什么真正的架构或DDD。它只是基本的OO(多态)。

  • 如果您的起始点是一只宠物并且您想要触发特定于其物种的行为,那么没有秘密 - 调用者必须知道宠物是哪个子类型并使用其真实子类型引用该对象,而不是{ {1}}。

  • 如果您的起点是Pet并且您想要在其全部或部分宠物中调用某些行为,则需要推理更抽象的内容。如果我很好地理解了这个领域,那就像“人类可以告诉动物进行的动作”。

    找到正确的名称后,在Human上创建一个具有该名称的抽象方法,让Pet的每个子类以自己的方式实现它。然后,由于多态性,无论是猫,狗还是大象,你都可以告诉一组宠物。