2012-10-11 95 views
6

我试图用一组全面的属性来模拟产品。通常,在线商店会使用文本描述来列出特定产品的属性。但是,这种解决方案并不是最优的。深层继承层次结构的替代方法?

例如,下面的链接显示属性不一致的同一产品文字描述中,但不同厂家:

因此,我选择了继承层次结构如下:

Product>Component>GraphicsCard>NvidiaGraphicsCard

这样做的原因是因为我想在每个Product的属性细粒度控制。这使我可以包含特定于NvidiaGraphicsCard的属性,这些属性不适用于ATiGraphicsCard

请注意,除了向子类添加更多字段之外,继承还允许我使用多态性,使OrderItem拥有对Product的引用。这是我排除构图的原因。

有这么深的继承层次结构有问题吗?如果有的话,是否有解决方案或可能模式来解决这个问题?

回答

8

由于几个原因,深层继承层次结构在DDD和ORM环境中存在问题。当您尝试定义实体的身份时会出现一个问题。 A Product必须与基于身份的其他产品相媲美,而不管哪个子级正在进行比较。该功能可以在Product类中提供,但必须注意确保子类也可以进行比较,并且有几个疑难问题。例如,NHibernate将为类生成一个代理,以便该对象的实际运行时类型不会是NvidiaGraphicsCard,而是从它继承的代理。虽然NvidiaGraphicsCard的瞬态实例将不是代理。这意味着你不能根据类型进行比较。

另一个难点是配置ORM映射来支持继承。虽然大多数ORM允许,但生成的映射和生成的SQL通常很复杂。你是否将所有的子类存储在一张表中?在具有外键的多个表中共同使用一个产品表?在前者中,你会得到一张巨大的桌子。在后一种情况下,您的查询将受到影响,因为所有的子类表都需要加入。关系模型和对象模型之间的阻抗失配太多了。事件如果使用文档数据库,最好将组合优于继承。

相反,我会去找一个Product类,它可以由产品特定的描述符或属性字典组成。这将使OrderItem引用Product而不知道具体的产品类型 - 不需要多态性。这也将使得更容易获得新类型的产品 - 不需要创建新的子类。

1

这是一本教科书继承的例子,一个很好的例子。我发现这样的模型没有什么问题,只不过在关系型数据库中坚持它会很困难。

另一方面,有时一组属性只与无法通过单一继承表达的项目子集相关。例如。 PowerConsumption描述给予产品需求多少功率与鼠标和USB记忆棒无关。另外重量对于某些组件并不重要。这意味着您可能会调查具有特质的语言,例如Scala,以尽可能使您的模型变为DRY。

请注意,没有深度继承的性能损失 - 较长的继承链并不意味着较慢的虚拟方法调用(并且,由于这些只是数据容器,因此您不会使用虚拟调用)。

0

我会建议你看看装饰模式。这样你就可以拥有你所需要的任何技巧和少于十亿的课程。