2011-11-28 83 views
1

在我之前線程的延續中,我發現很多類都包含集合。例如:其中包含集合的類設計,其中的集合

引擎 - 包含活塞的集合 - 活塞 - 包含的XYZ部分集合

因此,有層次,因爲每個組件包含零件的集合,它的推移和。

這是我以前沒有遇到的編碼場景。不斷地編寫代碼,像這樣:

class Part (Replace Part with apt name) 
{ 
List<APart> parts ... 
} 

然後同爲分開,因爲它包含內部部件的集合,是非常繁瑣的,因此讓我懷疑這是否是代碼的正確途徑。

有沒有更好的方法來寫這種代碼?像AOP等任何東西我都會接受(儘管AOP是針對橫切關注的)。

+0

方面:堅持Demeter法(http://en.wikipedia.org/wiki/Law_of_Demeter)通常是一個好主意。收藏集會誘使你使用多個「點」。抗! – TrueWill

+0

你怎麼能在這裏呆了這麼久,不知道這些不是線程? –

回答

2

一個念頭:

引擎類可能含有活塞經理班,管理名單皮斯噸PistonsManager可能包含所有的邏輯來修改列表並屏蔽引擎類別不必考慮活塞。按照相同的邏輯,你的類可以包含一個XYZPartsManager。通過這種方式,您不需要編寫列表邏輯/管理到您的引擎邏輯,但有類可以做到這一點。它可能會使可讀性和良好的邏輯流程。

+0

這給了我一些啓發。 – dotnetdev

1

有時候編碼是單調乏味的。但是,通常會有一些模式可以從實現中挖掘出來。

我們有一個類似於你的情況,並發現有一個潛在的遞歸模式。所以我們實現了一個基類(稱之爲Part),它本身可以包含List(Of Part)。這可以根據需要儘可能深。

特定類實現的集合類是特定類型的泛型集合,或者實現一個接口,允許我們獲取類中的特定數據(由於WCF中的集合衝突,我們必須實現接口機制)。

結果是,你可能會有很多分立的部分繼承者,但你的意志將是一個常見的方式來實例化,處理和遍歷你的元素與一套共同的代碼。

更新

這是一個嚴重的人爲的例子,而是一個應該讓你在正確的方向。在我們的應用程序中,我們使用大量的反射和表格映射類名來嚴格減少重複代碼的數量。這個例子反映了一些這種行爲,但不是全部。

這個例子基本上顯示了你如何擁有一個通用零件類,它包含一個零件的遞歸集合,這些零件在零件類型層次被索引。換句話說,您將使Engine和Engine擁有按部件類型索引的部件集合集合。例如,引擎可以包含一系列活塞,一系列軟管等。這種設計顯然是可選的,但確實使它更容易處理。

以下是主要類別:

/// <summary> 
/// The base part collection 
/// </summary> 
/// <remarks></remarks> 
public class PartBase 
{ 
    /// <summary> 
    /// The key for the record, such as a recordid 
    /// </summary> 
    /// <value></value> 
    /// <returns></returns> 
    /// <remarks></remarks> 
    public virtual string CollectionKey {get; set;} 

    public PartBase() : base() 
    { 
     m_cParts = new PartBaseCollections(); 
    } 

    public virtual void InitializeFromDataRow(DataRow oRow) 
    { 
     // ToDo: Either implement generic column/datarow mapping through reflection or have each class override this method 
    } 

    private PartBaseCollections m_cParts; 

    public PartBaseCollections Parts 
    { 
     get 
     { 
      return m_cParts; 
     } 
    } 

    public PartBaseCollection GetParts(string sTableName) 
    { 
     if (this.Parts.Contains(sTableName)) 
     { 
      return this.Parts(sTableName); 
     } 
     else 
     { 
      PartBaseCollection cParts = new PartBaseCollection(sTableName); 
      this.Parts.Add(cParts); 
      return cParts; 
     } 
    } 

    public void AddParts(DataSet dsData) 
    { 

     foreach (DataTable oTable in dsData.Tables) 
     { 
      PartBaseCollection cParts = null; 

      cParts = GetParts(oTable.TableName); 

      cParts.AddRecordsFromTable(oTable); 
     } 
    } 

} 

/// <summary> 
/// A collection of PartBases keyed by a value, such as a table name (for example, Pistons) 
/// </summary> 
/// <remarks></remarks> 
public class PartBaseCollection : System.Collections.ObjectModel.KeyedCollection<string, PartBase> 
{ 

    public string CollectionKey {get; set;} 
    public Type RecordType {get; set;} 

    public PartBaseCollection(string TableName) 
    { 
     this.CollectionKey = TableName; 
     // Assume that the TableName is a class in the current namespace 
     RecordType = Type.GetType(this.GetType().Namespace + "." + TableName, false, true); 
    } 

    protected override string GetKeyForItem(PartBase item) 
    { 
     return item.CollectionKey; 
    } 

    public PartBase ManufactureRecord() 
    { 
     return Activator.CreateInstance(this.RecordType); 
    } 

    public void AddRecordsFromTable(DataTable oTable) 
    { 

     foreach (DataRow oRow in oTable.Rows) 
     { 
      PartBase oPart = null; 

      oPart = ManufactureRecord(); 
      oPart.InitializeFromDataRow(oRow); 

      this.Add(oPart); 
     } 
    } 
} 

/// <summary> 
/// All of the PartBaseCollection elements for a given PartBase 
/// </summary> 
/// <remarks></remarks> 
public class PartBaseCollections : System.Collections.ObjectModel.KeyedCollection<string, PartBaseCollection> 
{ 

    protected override string GetKeyForItem(PartBaseCollection item) 
    { 
     return item.CollectionKey; 
    } 
} 

public class Engine : PartBase 
{ 

} 

public class Piston : PartBase 
{ 

} 

,這裏是創造了發動機的一個例子:

public void CreateEngine() 
{ 

    DataSet dsData = new DataSet(); 
    DataTable oTable = new DataTable("Piston"); 

    dsData.Tables.Add(oTable); 

    Engine oEngine = new Engine(); 

    oEngine.AddParts(dsData); 
} 
+0

+1。我總是贊成寫基礎班! – MattW

+0

小心分享樣品? – dotnetdev

+0

@dotnetdev:我添加了一個(相當)人爲的樣本,但它基於我們目前的工作而鬆散。顯然,實際的實現需要反映你從哪裏獲取數據,但我強烈建議使用反射來將數據移入和移出數據結構。這爲我們節省了數以萬計的其他重複代碼。 –

相關問題