2011-02-14 15 views
0

如果我需要一個從文件加載其數據的類(同時將加載函數保留在不同的類中),什麼是正確的(或良好的)設計?用於從文件加載數據的C#類設計

這就是我現在擁有的。不禁覺得有一個更好的方式來構建它的一切,但。絆倒我的部分是Loader必須在繼續之前調用Primary中的方法。

class Primary { 
    public int x1, x2, x3; //data that is read from file or calculated 

    public void LoadPrimary { 
    Loader L = new Loader(); 
    L.Load(this); //pass self as parameter (this can't be the best way though) 
    } 

    public void DoStuff() { 
    x1++; x2--; 
    } 
} 

class Loader { 
    public void Load(Primary PrimToLoad) { 
    PrimToLoad.x1 = 2; PrimToLoad.x2 = 4; 
    PrimToLoad.DoStuff(); //call a method in the calling class (better way for this?) 
    PrimToLoad.x3 = 6; 
    } 
} 

class Stub { 
    public void SomeMethod() { 
    Primary P = new Primary(); 
    P.LoadPrimary(); 
    } 
} 

在我真正的代碼,我使用Loader類來封裝從各種來源讀了幾種不同格式(所以有多個負載功能),否則,我只想包括主要功能,用它做。有沒有辦法讓Loader類返回主而不是void(現在它傳遞一個Param)。這似乎太「耦合」成爲這樣的好設計。

有更好的方法來完成這種情況的任何建議?我認爲這很常見,但只是不太瞭解課堂設計或術語,以便在google/SO/etc上找到答案(您如何在詞典中搜索不能拼寫的單詞)。

更新/ Notes的
兩個問題的答案(到目前爲止)向工廠模式點。這是否意味着對於每個Load方法,我必須有一個單獨的類?似乎在我的特殊情況下過度殺傷。這不也意味着我的Stub類必須知道/決定文件的格式(因此它可以調用正確的工廠類),而不是讓Primary類擔心它嗎?似乎是封裝交易耦合。

肯定知道我應該使用屬性(實際上)和一個接口(實際上),但想要簡化它的問題。沒有考慮注射方面這是一個很好的建議。

如果任何人都可以更新他們的答案,以顯示多個加載函數如何工作(請保持簡單),我很可能會接受。我還在考慮將加載函數移回到Primary類中作爲替代解決方案。

+0

我想是不是在課堂上執行任何邏輯的好方法,它負責裝載數據(數據訪問層,就像你的`Loader`類) 。 – whyleee 2011-02-14 21:26:58

+0

@whylee - 絕對同意你的觀點。這就是爲什麼我試圖把DoStuff函數放在Primary類中而不是在Loader類中。只是不知道這是否是正確的方式。 – ktharsis 2011-02-14 22:41:13

+0

如果可能,在`LoadPrimary()`方法中,您可以先調用`Loader.Load()`方法,然後調用`DoStuff()`方法。 – whyleee 2011-02-14 22:59:22

回答

1

這看起來像一個非常簡單的工廠模式的例子。你不想讓創建的對象知道工廠。因此,撕裂了LoadPrimary(),並做到這一點,而不是:

class Primary { 
    public int x1, x2, x3; //data that is read from file or calculated 

    public void DoStuff() { 
    x1++; x2--; 
    } 
} 

public interface PrimaryFactory 
{ 
    Primary Load(); 
} 

public class FileTypeAPrimaryFactory { 

    FileTypeAPrimaryFactory(File f) 
    { 
     ... 
    } 

    public void Load() { 
     var item = new Primary(); 
     item.x1 = 2; PrimToLoad.x2 = 4; 
     item.DoStuff(); 
     item.x3 = 6; 
    } 
} 

public class FileTypeBPrimaryFactory { 

    FileTypeBPrimaryFactory(File f) 
    { 
     ... 
    } 

    public void Load() { 
     var item = new Primary(); 
     item.x1 = 2; PrimToLoad.x2 = 4; 
     item.DoStuff(); 
     item.x3 = 6; 
    } 
} 

class Stub { 
    public void SomeMethod() { 
    PrimaryFactory factory = PrimaryFactory(<get file>); 
    Primary P = factory.Load(); 
    } 

    public PrimaryFactory(File file) 
    { 
     if (<check file format>) return new FileTypeAPrimaryFactory(file); 
     return new FileTypeBPrimaryFactory(file); 
    } 
} 
2

有幾十種模式可以完成這項任務,您選擇的模式取決於系統的複雜性,靈活性和可擴展性。

你的解決方案並不可怕,但我會建議創建一個接口,ILoader,並用Loader實現它。此外,不是在主服務器中「新建」一個Loader,而是在構造函數中或在主服務器上使用一個屬性,將012oILoader放入Primary。如果你願意的話,你仍然可以保持一個默認的實現,即一個具體的Loader的新聞。這裏有一個例子:

class Primary { 
    public int x1, x2, x3; //data that is read from file or calculated 
    private ILoader _loader; 

    public Primary(ILoader loader) { 
    _loader = loader; 
    } 
    public Primary() { 
    _loader = new Loader(); 
    } 

    public void LoadPrimary { 
    _loader.Load(this); 
    } 

    public void DoStuff() { 
    x1++; x2--; 
    } 
} 

interface ILoader { 
    void Load(Primary primToLoad); 
} 

class Loader : ILoader { 
    public void Load(Primary PrimToLoad) { 
    L.x1 = 2; L.x2 = 4; 
    L.DoStuff(); //call a method in the calling class (better way for this?) 
    L.x3 = 6; 
    } 
} 

class Stub { 
    public void SomeMethod() { 
    Primary P = new Primary(new Loader()); 
    P.LoadPrimary(); 
    } 
} 

這種方法使你的依賴關係顯式給你的客戶。它還允許您使用ILoader的模擬實現進行測試。另外,你可以很容易地改變你的ILoader的實現來使用數據庫,網絡服務等。

另外需要注意的是我並不是特別喜歡將你的對象傳入Loader並讓Loader修改它。我寧願實例化一個Loader,並要求它從頭構建一個對象。當要求其他物體改變我自己的東西狀態時,我總會感到不舒服。這個實現看起來像一個工廠模式。

還有一個小問題,我看到你正在爲你的數據使用公共字段。這是一個很大的禁忌,你應該使用C# properties。屬性支持封裝和二進制兼容性。

您可能要考慮的另一種數據訪問策略是Active Record-設計不好,但容易理解實現並適用於小型系統。