2011-05-03 236 views
2

我有私有setter(或專用字段和與其關聯的Readonly屬性)應具有屬性的類。如果我在這些類中有靜態工廠方法來創建實例,那沒關係。然而很多開發人員寫道:「靜態工廠方法是建築黑洞」,因爲它不可能繼承靜態方法。靜態工廠方法vs工廠

C#沒有友好的類,因此我無法使用工廠來完成。

您對使用靜態工廠方法有什麼看法?

+1

爲什麼你無法在構造函數中傳遞值? – 2011-05-03 15:03:16

回答

2

作爲默認,我會通過將必需的參數傳遞給構造函數來創建實例。如果構造函數有多個參數,您需要一個parameter object或者您違反了SRP。如果根據參數有多種創建實例的選擇,並且邏輯並不比靜態工廠方法複雜,可能是在類中保持創建邏輯的最佳方式。

如果您有複雜的實例創建規則,這些規則依賴於參數以及可能使用工廠的其他因素,也許流利的工廠會收集所有必需的參數,然後使用類公共構造函數創建對象。

+0

感謝您的回答,但是什麼意思是「如果您根據參數創建實例有多種選擇」? – Danil 2011-05-04 09:47:19

+0

好吧,想象你需要實例化一個電子郵件發送類。可以有多個構造函數。需要遠程地址和用戶以及密碼的人。一個需要一個文件夾。一個採用禁用電子郵件發送的bool參數。現在您有多種創建實例的選擇,這取決於用戶提供的參數。使用工廠方法或流利的工廠來創建這個類使得代碼更富有表現力。 – 2011-05-04 10:53:45

0

如果目標和工廠不在同一個程序集中,獲取寫入方法的部分封裝的一種方法是使用私有接口實現,而您不需要客戶機代碼。

internal interface IMyClassFactorable 
{ 
    string MyProperty{ set; } 
} 

public class MyClass : IMyClassFactorable 
{ 
    private string _myProperty; 
    public string MyPrperty { get { return _myProperty; } } 
    string IFactoryable.MyProperty { set { _myProperty = value; } } 
} 

,或者與內部制定者如果工廠和目標是在同一程序

public class MyClass 
{ 
    public string MyPrperty { get; internal set; } 
} 
1

我不認爲聲明:

C#不具有友好的類, 因此我不能這樣做使用工廠

是真的。

關鍵是不要在正在執行實現的類上創建靜態工廠方法。你不會在這裏逃避強大的偶合。

你可能想看看依賴注入/倒置。您不必擔心創建工廠,而是通過/ code config設置您的對象是如何創建的; DI框架爲您提供工廠,併爲您指明需要的任何依賴關係進行佈線。

1

你必須以這種或那種方式製造這個「黑洞」。你可以使用構造函數,這很容易。但是,我發現靜態方法更好。它們幾乎共享構造函數的所有體系結構屬性,除了稍微好一些之外,構造函數必須始終創建一個新實例,因此某些實現抽象對構造函數來說是不可能的。

所以,答案是:請使用靜態方法! :)

2

類的所有隻讀依賴項應該由此類型的構造函數注入。這使代碼更容易理解,調試,並且最重要的是測試。所以如果這是不可能的,那麼真的應該考慮你的類層次結構。如果你仔細地遵循這個原則,你也可以使用依賴注入框架在運行時解決這個依賴關係。

樣品:

class Foo : IFoo 
{ 
    private readonly IBar bar; 
    private readonly IBaz baz; 

    public Foo(IBar bar, IBaz baz) 
    { 
     this.bar = bar; 
     this.baz = baz; 
    } 

    // Readonly properties for bar and baz, if needed. 
} 
1

我相信,當人們說靜態工廠方法「... [被]建築黑洞」,他們指的是,這是一個爛攤子,延長工廠方法的問題。判斷點是創建的類是多麼複雜。如果它們是重量級的,那麼從長遠來看,可能的靜態工廠方法將會變得混亂。

C#確實擁有「內部」修飾符,它不會替代朋友,只要其他人在您的班級工作,但重要的是您能否在未來擴展工廠而不是其他人,你可以將工廠和創建的類打包爲一個獨立的程序集,並使用「內部」,如「朋友」。

而且,是的,這是使用C#時遇到的問題。相互矛盾的要求削弱了對老友好工廠的支持,這是痛苦的。如果你不能使用「內部」,並且你的工廠正在渲染重量級的類,那麼實際上沒有其他辦法可以爲類添加「InitInstance()」類型的方法,這樣就可以擴展「製造過程」。