2017-08-26 49 views
1

我有一個工廠,創建了廣泛通過我的應用程序使用的對象。工廠創建的一些對象需要另一個依賴關係。此可選依賴項是一個接口/類,其中包含來自本地設置文件的設置。目前,工廠界面和設置界面都被注入了20個類。雖然,類的數量會少些,如果應用程序繼承樹是不是6-7級深(指的IFactory和ISettings至6個構造獲得通過,並最終在一個基類,它其分配給一個領域到達)。是否在工廠持有信息,而不是將其通過調用代碼任何意義?

深層繼承不會很快發生變化,但我認爲可以通過從它們中刪除ISettings並將其放入IFactory實現本身來減輕這些構造函數的負載。該ISettings將通過構造函數中注入混凝土工廠,然後強似的ISettings作爲Create()方法的一部分,它只是使用工廠ISettings只讀屬性。一旦程序啓動,這些設置保證不可變。

這是否以任何方式皺起了眉頭,有沒有更好的方法來解決這個問題?一些同事認爲工廠應該幾乎從不保持狀態......但他們不知道是什麼原因。

這些都是類似的問題,我發現,這給了答案,但我仍然在尋找一個更充實的答案,如果可能的話。

Adding Properties to Abstract Factory

Abstract Factory Pattern and Properties

簡單的例子:

interface IObjValidator 
{ 
    bool Validate(); 
} 

interface IObjValidatorFactory 
{ 
    IObjValidator Create(); 
} 

class ObjValidatorFactory : IObjValidatorFactory 
{ 
    // Is it OK for the factory to hold this field? 
    private readonly ISettings settings;  

    public IObjValidator(ISettings settings) 
    { 
     this.settings = settings; 
    }  

    IObjValidator Create(ObjValidatorMode mode) 
    { 
     switch(mode) 
     { 
      case ObjValidatorMode.One: 
       return ObjValidator1(); 

      case ObjValidatorMode.Two: 
       return ObjValidator2(this.settings); 
     } 
    } 
} 

class ObjValidator1: IObjValidator 
{ 
    public bool Validate() 
    { 
     // Do stuff. 
    } 
} 

class ObjValidator2: IObjValidator 
{ 
    private readonly ISettings settings; 

    public ObjValidator2(ISettings settings) 
    { 
     this.settings = settings; 
    } 

    public bool Validate() 
    { 
     // Use ISettings field data here.    
    } 
} 

回答

1

這是否以任何方式皺起了眉頭,有沒有更好的方法來解決這個問題?

不正確的方法來解決這一問題將是有驗證程序使用Settings.getInstance訪問Singlteon設置類。這是令人不悅的。在問題中提到的方法實際上剷球,一個單身的設置類將相繼推出的所有問題,因此是正確的前進道路。

不過,有一件事我會改變的是我會做的ObjValidatorFactory類依賴的ISettingsFactory接口,而不是依賴於ISettings直接。這將創建重定向從客戶端類的ISettings實施ObjValidatorFactory的責任。

class ObjValidatorFactory: IObjValidatorFactory 
{ 
    private ISettingsFactory settingsFactory; 

    public ObjValidatorFactory(ISettingsFactory settingsFactory) 
    { 
     this.settingsFactory = settingsFactory; 
    } 

    IObjValidator Create(ObjValidatorMode mode) 
    { 
     //source could be the file name for example 
     ISettings settings = settingsFactory.Create(source); 
     switch(mode) 
     { 
      case ObjValidatorMode.One: 
       return ObjValidator1(); 

      case ObjValidatorMode.Two: 
       return ObjValidator2(settings); 
     } 
    } 


} 

工廠可以如下實例:

ISettingsFactory fileSettingsFactory = new FileSettingsFactory(); 
IObjValidatorFactory objectValidatorFactory = new ObjValidatorFactory(fileSettingsFactory); 
objectValidatorFactory.Create(ObjValidatorMode.STRICT); 
+0

很好解釋了答案,我同意除了這一點:設置工廠似乎是過度殺傷(在我的情況下),因爲將只有一個設置,在應用程序會話開始時創建並傳遞給ObjValidatorFactory。我無法想到一個好處,但我歡迎被告知爲什麼我錯了。 – user2079828

+1

@ user2079828「ISettings」接口的存在表示將來可能會有多個設置的實現可以從不同的源(文件,數據庫等)加載。如果不是的話,那麼你可以用'ISettingsFactory'做的路程,在例如ObjectValidatorFactory'的''的方法Create'直接創建'Settings'的一個實例。 – CKing

+0

啊,是的,我明白你爲什麼現在提出這個建議。我相信ISettings完全是爲了Mocking的目的而創建的。我現在同意,正如你所指出的那樣,在工廠中創建設置是最好的主意。 – user2079828

1

我寧願避免,如果我能,一切都是平等的,如果ObjValidator2在某種程度上具有不同的驗證取代(例如, ObjValidator2a),

A.)你現在必須改變你的構造函數來接受一個se ttings object objValidator2a B.)將它從構造函數中刪除,因爲objValidator2a不需要objValidator2的設置。)將構造函數保持原樣,知道傳遞的設置永遠不會被使用。

因人而異

+0

我同意你的意見和upvoted它 –

+0

的機會,「A」是這個代碼庫中幾乎不存在的,但這樣的結果會有如此糟糕?工廠現在將擁有兩個設置文件,而不是「再次」通過20個類注入另一個對象,幾乎沒有任何理由。對於C來說,它肯定是Factory的一個可選依賴項,但我傾向於在20個其他類中擁有該可選依賴項。思考? – user2079828

+0

CKings答案看起來不錯。如果你有在對象驗證的源代碼控制的另一種方法是刪除設置加載在構造和創建另一個接口方法加載設置(例如無效LoadSettings(設置設置)),並有一個SettingsLoader類有一個單一的責任調用已創建實例的LoadSettings方法。只要選擇適合您的代碼庫的「更合適」即可。 – Goose

0

幾點意見: - 並非所有的驗證需要ISettings - 對象是基於模式

在這種情況下創建的,我認爲抽象工廠服多,分解責任到子類。

可以在Factory類中有字段,它將負責分解同一個對象,想象餅乾工廠總是創建一個相同的餅乾。

的樣子,你已經定義了工廠類,可能會導致內容耦合。將來,您將開始注入越來越多的不可維護的依賴項。

另一種方式是將預先構建的驗證器作爲地圖注入工廠,然後在create()中從地圖獲取條目。

+0

你能告訴我你的意思「注入預構建的驗證在工廠地圖......」什麼。此外,驗證器是幾乎所有的成品,有被創造更多類型的機會很小,但即使在未來更校驗不會把其他靜態的和不可改變的數據進廠是比甚至更多的東西注入到更好20個其他課程?它感覺更易於維護和閱讀。 – user2079828

相關問題