2012-10-22 73 views
0

我正在研究一個項目,我正在試圖從一個持久模式轉移到另一個模式。持久性設計模式

我看着在模式企業應用架構的,設計模式,並在這裏this MSDN文章尋求幫助。我們目前的模式是MSDN文章中描述的活動記錄模式。作爲邁向更多模塊化代碼庫的第一步,我們試圖將我們的一些業務對象(又名錶)分解爲多個接口。

因此,舉例來說,假設我有一個商店應用程序是這樣的:

public interface IContactInfo 
{ 
    ... 
} 

public interface IBillingContactInfo: IContactInfo 
{ 
    ... 
} 

public interface IShippingContactInfo: IContactInfo 
{ 
    ... 

} 

public class Customer: IBillingContactInfo, IShippingContactInfo 
{ 
    #region IBillingContactInfo Implementation 
    ... 
    #endregion 

    #region IShippingContactInfo Implementation 
    ... 
    #endregion 

    public void Load(int customerID); 
    public void Save(); 
} 

Customer類代表了我們的客戶表中的一行。即使Customer類是一行,它實際上也實現了兩個不同的接口:IBillingContactInfo,IShippingContactInfo。

從歷史上看,我們沒有那兩個接口,我們只是在整個Customer對象周圍傳遞這些接口,然後做出我們想要的任何更改並將其保存。

這裏是問題出現的地方。現在我們有了這兩個接口,我們可能有一個控件需要一個IContactInfo,將其顯示給用戶,並允許用戶在錯誤的情況下進行糾正。目前我們的IContactInfo接口沒有實現任何Save()以允許對其進行修改。

有關良好設計模式的任何建議,以避免此限制而無需完全切換到其他衆所周知的解決方案?我真的不想通過併爲我的所有接口添加Save()方法,但它可能是我最終需要做的。

+0

也許我錯過了這個觀點..但是你不能只在'IContactInfo'接口中包含'Load'和'Save'方法嗎? –

+0

如果控件需要Save()的能力,爲什麼要採用IContactInfo?如果可能創建一個實現IContactInfo的SavableContactInfo類型,然後讓該控件獲取一個SavableContactInfo對象? – itsme86

+0

@SimonWhitehead我可以包含一個Load和Save,但有近100個表格,我們可能會將這些表格分解到接口中,以便確保在開始沿着這條路線前,我不會錯過更明顯和更好的戰鬥測試。 –

回答

0

通過簡單地使IContactInfo實現IPersistable接口,您可以輕鬆地將Save()方法約束添加到繼承的接口,該接口要求使用Save()方法。那麼,所有具有IContactInfo的東西也有IPersistable,因此必須有Save()。您也可以使用ILoadableLoad(int ID) - 或者更多的語義正確性IRetrievableRetrieve(int ID)來做到這一點。

儘管這完全取決於您如何使用ContactInfo對象。如果這與您的使用情況無關,請留下評論/更新您的問題,我會重新回答我的答案。

+0

我同意我們可以有'IPersistable',但我們必須將其添加到每個接口。在我的示例中,如何解決使用Save()? IBillContactInfo.Save()或IShippingContactInfo.Save()?我想我必須回到顯式的接口實現上來,我擔心這會是一個真正的痛苦,儘管我認爲我必須用兩個接口來做這件事,所以這可能是我最好的選擇。我希望有一個我沒有看到的神奇的子彈:)這也只是一個例子,所以不要太在意它。重要的問題是接口繼承命名衝突。 –

+0

我的建議是將其添加到基礎'IContactInfo'接口,然後由它下面的所有接口繼承。至於「它的哪個版本」無關緊要,你只是簡單地履行由「IPersistable」或其他方式所規定的合同。沒有任何可以調用的「版本」。您可能會對類繼承和重寫產生困惑,它有自己的語義。 – tmesser

1

您計劃擁有多少種IContactInfo的衍生產品?

也許我錯過了點,但我認爲你會做一個叫做ContactInfoBillTo類,並在每一個Customer實例ShipTo更好。由於您的IShippingContactInfoIBillingContactInfo接口繼承自相同的IContactInfo接口,因此您的類將使用一組字段滿足IContactInfo基本接口。這將是一個問題。

最好讓這些獨立的實例。然後,保存你的Customer更直截了當。

你打算進行持久化或保存到數據庫或其他東西的序列化?

使用Customer和ContactInfo的具體類型肯定會覆蓋前兩個。

(平面文件將努力爲您的原始設置,但我希望你是不是對規劃。)

我認爲這一切都歸結到你期望多少IContactInfo的衍生物有。在你的圖中有更多的地形是沒有問題的。如果這意味着一個包含多個部分的記錄(您的示例),或者如果這是一對多關係(我的示例),或者它是多對多列出類型(ShipTo,BillTo等)。 )在連接表中。多對多確實減少了客戶和各種ContactInfo類型之間的關係,但是當您需要具體的關係時,它會在場景的應用程序開發中創建開銷。

+0

謝謝你的回答。我們堅持保存到數據庫,儘管你是對的,我們可以將這個實現抽象出來並使用其他的東西,如緩存和序列化。爲了簡化持久性,我們使用反射將數據庫列直接移動到屬性,反之亦然。創建多層對象會更可取,但會使我們的ORM策略複雜化,因此我們正在使用接口。另外,我不明白具體類型如何解決我的問題不僅僅是接口?你會介意更多,因爲我錯過了它。 –

+1

@MarkRucker,實現從同一接口繼承的兩個接口肯定會在將對象映射到表時產生問題,並且接口不會序列化。而且,雖然界面很有價值,但它們不是替代良好階層的替代品。如果您擔心派生類型,不要害怕使用按表繼承。 –