工厂模式:将对象构造限制为工厂

时间:2019-06-23 08:07:54

标签: c# .net design-patterns

我有一个类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#,但这可能是一个更普遍的问题)

3 个答案:

答案 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 { }
}