如何确保某个类仅由工厂实例化而不是直接调用 new ?
编辑:我需要将工厂作为一个单独的类(用于依赖注入),所以我不能使它成为实例化类的静态方法,所以我不能将新设为私有。
答案 0 :(得分:22)
如果工厂位于同一个程序集中,并且只需要保护外部程序集实例化该类,则可以将构造函数设置为内部。我知道阻止所有其他类(包括同一程序集中的类)的唯一方法是使实例化的类成为工厂的嵌套私有类,并仅将其作为接口公开。如果类是它自己的工厂(静态工厂方法),那么你可以像其他人提到的那样将构造函数设为私有。
答案 1 :(得分:11)
将其构造函数设为私有,并将类方法作为静态方法提供给类本身。
在大多数情况下,您可以将构造函数设置为内部,允许您将工厂分解为自己的类 - 我发现通常不值得尝试阻止我自己的团队使用new
创建实例在班级组装中。
答案 2 :(得分:5)
使构造函数内部并将工厂安置在同一个程序集中。
public MyClass
{
internal MyClass()
{
}
}
在同一个程序集中
public MyClassGenerator
{
public static CreateMyClass()
{
return new MyClass();
}
}
如果工厂不能在同一个组件中,或者此方法不适合您,请查看Dan's answer
答案 3 :(得分: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;
}
是的,这很麻烦且很尴尬。但可能有一些奇怪的情况,这实际上是一个很好的解决方案。
答案 4 :(得分:2)
您可以使用工厂类中的公共构造函数将具体类作为嵌套私有类 - 这样您的工厂就可以创建它们,其他人甚至看不到它们。 无论如何,你从工厂返回一些接口/抽象类,而不是具体类型。 当然,您无法将返回类型转换为客户端代码中的某个具体类型,但首先它是设计错误的标志,其次您可以使用嵌套私有类继承的更具体的接口/抽象类来解决它。
你可以在这里参考Eric Lippert的答案(针对类似的问题): Why Would I Ever Need to Use C# Nested Classes
答案 5 :(得分:1)
它将始终通过调用new somewhere 来创建,但如果您只想在工厂类中进行,则可以将所有构造函数设置为Internal(或Private),并使用Public Static同一类的工厂方法)。
答案 6 :(得分:1)
很多人都提到过使用internal,但是你也可以使你的构造函数受到保护,并派生出一个只有静态工厂方法的类。这并不妨碍其他人做同样的事情,但在限制对构造函数的直接访问方面做得相当不错。
答案 7 :(得分:0)
我不喜欢在类型本身上拥有工厂,特别是如果它是域对象。如果你有一个单独的班级作为工厂(我认为你应该),那么内部。如果工厂位于不同的组件上,请使用InternalVisible属性。