我正在尝试使用一组综合属性对产品进行建模。通常,在线商店会使用文本描述来列出特定产品的属性。但是,这种解决方案并不是最佳的。
例如,以下链接显示同一产品的文字说明中的属性不一致,但制造商不同:
因此,我选择了一个继承层次结构如下:
Product
> Component
> GraphicsCard
> NvidiaGraphicsCard
之所以这样,是因为我希望对每个Product
的属性进行细粒度的控制。这允许我包含特定于NvidiaGraphicsCard
的属性,这些属性不适用于ATiGraphicsCard
。
请注意,除了向子类添加更多字段之外,继承还允许我使用多态来使OrderItem
保持对Product
的引用。这就是我排除作文的原因。
拥有如此深层次的继承层次结构是否有问题,如果有,是否有任何解决方案或模式来处理此问题?
答案 0 :(得分:8)
由于某些原因,深层继承层次结构在DDD和ORM的上下文中存在问题。当您尝试定义实体的身份时,会出现一个问题。无论哪个子类被比较,Product
必须与基于身份的其他产品相比较。可以在Product
类中提供此功能,但必须注意确保也可以比较子类并且存在一些问题。例如,NHibernate将为类生成代理,因此对象的实际运行时类型将不是NvidiaGraphicsCard
,而是从其继承的代理。虽然NvidiaGraphicsCard
的瞬态实例不是代理。这意味着您无法根据类型对它们进行比较。
另一个困难是配置ORM映射以支持继承。虽然大多数ORM允许它,但生成的映射和生成的SQL通常很复杂。您是否将所有子类存储在一个表中?在具有常用产品表的外键的多个表中?在前者你最终得到一个巨大的桌子。在后一种情况下,您的查询将受到影响,因为需要连接所有子类表。关系模型和对象模型之间存在太多的阻抗不匹配。事件如果使用文档数据库,最好支持组合而不是继承。
相反,我会选择一个Product
类,它可以由产品特定描述符或属性字典组成。这将导致OrderItem
在不知道特定产品类型的情况下引用Product
- 不需要多态性。这也可以更容易地允许新类型的产品 - 无需创建新的子类。
答案 1 :(得分:1)
这是一本继承的学校书籍例子,一个很好的例子。我认为这种模型没有任何问题,只是在关系数据库中持久存在会很困难。
另一方面,有时一组属性仅与无法通过单继承表达的项的子集相关。例如。 PowerConsumption
描述了产品需求的功率与鼠标和USB记忆棒无关。对于某些组件,重量也不是很重要。这意味着您可以调查具有特征的语言(如Scala),以使您的模型尽可能干燥。
请注意,深度继承没有性能损失 - 较长的继承链并不意味着虚拟方法调用较慢(好吧,您不会使用很多虚拟调用,因为这些只是数据容器)。
答案 2 :(得分:0)
我建议你看一下Decorator模式。通过这种方式,您将获得所需的任何技巧和不到10亿个课程。