我在属于不同聚合的几个实体中有一些共同的行为,我想在抽象类中考虑因素。
让不同聚合中的实体从公共抽象类继承是否有任何缺点?
有几个实体具有可以用不同语言翻译的名称,描述或其他属性。
例如,我会使用setName(language, name)
设置名称,并使用getName(language)
检索。
每种语言的每个文本都存储在一个对象中,例如:
class EntityName
{
protected Entity entity;
protected Language language;
protected String text;
protected int version;
public EntityName(Entity entity, Language language)
{
this.entity = entity;
this.language = language;
this.version = 1;
}
// setText(), getText(), ...
}
对于给定的Entity
班级,EntityName
在Entity
聚合内。只有Entity
可以通过EntityName
和setName()
创建,读取和写入getName()
。
但是,EntityName
,EntityDescription
,OtherEntityName
等类都会共享相同的代码。唯一不是更改的部分是对聚合的引用,因此也就是构造函数。
答案 0 :(得分:4)
关于这个话题并不多。但是,请看一篇名为How To: Domain Driven Design
的文章请特别阅读标题为第2步 - 识别聚合和聚合根的部分:
在高级情况下,类中存在多态性 模型也会影响聚合边界。这发生在时 多个聚合根类都共享相同的基类
如果您正在存储域模型之外的簿记数据(id,版本,创建时间戳,更新时间戳)(例如,为了支持您的持久层),我不认为这是一个问题。但是,如果您尝试重用真正的业务方法和属性,则可以考虑使用组合或AOP引入替换继承。
<强>更新强>
在查看更新的用例之后,看起来好像是在尝试实现代码重用而不是真正的Liskov is-a关系。有些语言更好地支持这种类型的重用,例如mixins(Groovy)或traits(Scala)。假设Java,您可以做的一种方法是创建一个类并使用Project Lombok的@Delegate注释转发到您的实现。这有以下好处:
我相信这更纯粹,并使您的模型具有灵活性。我在一些项目上使用了Project Lombok并取得了巨大的成功。它允许您支持Java中一些缺少的语言功能,并且更多地关注您的域,而不是实现某些习语所需的必要样板代码。
答案 1 :(得分:1)
我认为只要通用定义不影响聚合根设计就行。也就是说,您开始对聚合根进行建模,并注意它们有很多共同点,因此您可以提取公共基类。
但是,我会对此三思而后行,因为从不同的有界背景聚集根源的几率是多少?这是IMO的代码味道。答案 2 :(得分:0)
正确的继承由is-a
关系定义。 imho很少有适用于聚合根的情况。
仅仅因为根看起来相似并不意味着它们来自同一个地方。
如果您可以创建一个名称在域中有意义的基类,请继续。如果没有,请不要。