2010-09-08 25 views
6

如何確保某個類僅由工廠實例化,而不是通過直接調用新的確保對象僅由工廠創建(C#)

編輯:我需要的工廠是一個單獨的類(依賴注入的目的),所以我不能讓它類的靜態方法來實例化,所以我不能讓私人的。

回答

5

如果出於某種原因需要將工廠和構建的類放在單獨的程序集中(這意味着只需使用internal就行不通),並且您可以確保工廠有機會首先運行,可以這樣做:

// In factory assembly: 

public class Factory 
{ 
    public Factory() 
    { 
     token = new object(); 
     MyClass.StoreCreateToken(token); 
    } 

    public MyClass Create() 
    { 
     return new MyClass(token); 
    } 

    private object token; 
} 

// In other assembly: 

public class MyClass 
{ 
    public static void StoreCreateToken(object token) 
    { 
     if (token != null) throw new InvalidOperationException(
      "Only one factory can create MyClass."); 

     this.token = token; 
    } 

    public MyClass(object token) 
    { 
     if (this.token != token) throw new InvalidOperationException(
      "Need an appropriate token to create MyClass."); 
    } 

    private static object token; 
} 

是的,這很麻煩和笨拙。但可能會出現奇怪的情況,這實際上是一個很好的解決方案。

+0

我喜歡這個,除了有兩個問題...(1)你的例子似乎只允許我使用1個工廠。我想允許創建許多工廠(可能有不同的工廠風格),唯一的要求是必須使用Factory對象創建MyClass的對象。 (2)如果我用new()約束來使用泛型,那麼MyClass需要一個無參數的構造函數呢?你的例子在這種情況下不起作用。 – JoelFan 2010-09-12 23:36:40

+0

「你的例子似乎只允許我使用1個工廠。」使'token'靜態或以其他方式在不同的工廠實例中共享它。任何有權訪問該令牌的東西都可以創建'MyClass'的實例「如果我使用帶new()約束的泛型,那麼MyClass需要一個無參數構造函數?」那麼你也不需要工廠。 – munificent 2010-09-13 14:26:27

11

使其構造函數爲私有,並將該工廠方法作爲靜態方法提供給類本身。

在大多數情況下,您只需將構造函數設置爲內部函數,即可將工廠劃分爲自己的類 - 我發現通常不值得設法阻止自己的團隊使用new在類中創建實例' 部件。

5

將構造函數放在內部並將工廠放置在同一個程序集中。

public MyClass 
{ 
    internal MyClass() 
    { 
    } 
} 
在同一裝配

public MyClassGenerator 
{ 
    public static CreateMyClass() 
    { 
     return new MyClass(); 
    } 
} 

如果工廠不能在同一程序或此方法不爲你工作,看Dan's answer

22

如果工廠是在相同的程序集並且只需要保護實例化類的外部程序集,就可以使構造函數成爲內部函數。我知道阻止所有其他類(包括同一程序集中的類)的唯一方法是將實例化的類作爲工廠的嵌套私有類,並僅將其作爲接口公開。如果這個類是它自己的工廠(一個靜態工廠方法),那麼你可以像前面提到的那樣使構造函數保持私有。

+0

+1 - 如果你真的需要這個,這是如何完成它。 – 2010-09-08 19:59:01

1

它總是通過調用新的某處創建的,但是如果您只希望在工廠類中發生這種情況,您可以將所有構造函數設置爲Internal(或Private),並使用Public Static工廠方法同班)。

0

我不喜歡在類型本身上有工廠,特別是如果它是一個域對象。有內部如果你有一個單獨的類作爲工廠(我認爲你應該)。如果工廠位於不同的裝配上,請使用InternalVisible屬性。

1

很多人都提到過使用內部函數,但是你也可以讓你的構造函數受到保護,並派生一個只包含靜態工廠方法的類。這並不妨礙其他人做同樣的事情,但在限制直接訪問構造函數方面做得相當不錯。

2

你可以將你的具體類作爲嵌套的私有類,在工廠類中使用公共構造函數 - 這樣你的工廠就可以創建它們,其他人甚至不能看到它們。 無論如何,你從工廠返回一些接口/抽象類,而不是具體類型。 當然,你不能將你的返回類型轉換爲客戶端代碼中某個具體類型,但首先它是一個糟糕設計的標誌,其次你總是可以用更具體的接口/抽象類來解決它,因爲嵌套的私有類繼承。

,你可以參考埃裏克利珀的答案在這裏(對於類似的問題): Why Would I Ever Need to Use C# Nested Classes