2012-10-11 136 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

我會建議你看看裝飾模式。這樣你就可以擁有你所需要的任何技巧和少於十億的課程。