我有一个类T
和一个工厂TFactory
,该工厂创建了T
类型的对象。
我想确保仅允许工厂创建新的T
对象。
一个半心半意的解决方案是要求将工厂作为T
的构造函数中的参数,其唯一目的是只有至少带来工厂对象的人才能创建T
的: / p>
class T
{
public T(TFactory Tf)
{
if (!(Tf is TFactory))
throw new InvalidOperationException("No factory provided");
}
}
但是,无论手头有TFactory
,都可以构造T
。
另一种方法是通过堆栈跟踪检查,如果构造函数调用确实来自TFactory内部,但这对我来说似乎是过大的。
第三个方法是将T
和TFactory都放在它们自己的程序集中,这些程序是广告制作T
的构造函数internal
。但是仅仅为此目的有一个新的项目和组装吗?
有人有更好的主意吗? (尽管我的代码是C#,但这可能是一个更普遍的问题)
答案 0 :(得分:3)
这与您的第三种方法非常相似:将工厂声明为T
的内部类,并使T
的构造函数private
:
public class T {
public class Factory {
public T GetT() {
return new T(); // simple implementation just for an example here
}
}
private T() {}
}
由于Factory
位于T
内部,因此它可以访问私有构造函数,但外部代码不能。如果您不想创建单独的程序集,则可以考虑使用这种方法。
请注意,您仍然可以将工厂类和T
放在两个不同的文件中,并使用partial
类:
public partial class T {
private T() {}
// other stuff about T here...
}
// in another file
public partial class T {
public class Factory {
public T GetT() {
return new T();
}
// other stuff about Factory here...
}
}
答案 1 :(得分:2)
第二种方法是最糟糕的方法。对于客户来说,这种行为是绝对不明显和不清楚的。堆栈跟踪也会减慢执行速度。第一和第二很有意义。
如果要完全控制实例创建,则将其放入类型。使用工厂方法。请记住,在限制实例创建时应该合理。例如。实例应使用多态(虚拟)方法启动。不能从构造函数中调用这种方法(这是一种非常糟糕的做法),因此应在构造后调用该方法。为了不把责任放在客户端上,请将构造函数对一个隐藏,并提供一种工厂方法。
abstract class Base
{
protected abstract void Initialize();
}
class Derived : Base
{
protected Derived() { /* ... */}
protected override void Initialize() { /* ... */}
public Derived CreateDerived()
{
var derived = new Derived();
derived.Initialize();
return derived;
}
}
答案 2 :(得分:1)
public abstract class T { }
public class TFactory
{
public T CreateT() => new TImpl();
private class TImpl : T { }
}