如何使类工厂创建所需的派生类

时间:2013-02-20 10:12:33

标签: c# inheritance nested-class class-factory

我经常使用类工厂模式,其中类具有私有构造函数和静态方法来创建类。这允许由于某种原因无法构造类的情况,并返回null - 非常方便。

我希望能够将其扩展为工厂方法,该方法根据条件从派生类的层次结构中创建特定类。但是,我无法看到隐藏派生类的构造函数以强制使用工厂方法的方法。如果工厂方法在基类中,则它不再能够访问派生类的私有构造函数。将工厂方法放在每个派生类中都不起作用,因为必须事先知道所需的类型。如果一个类可以访问嵌套类的私有成员,嵌套类可能是一种方式,但遗憾的是,嵌套类似乎可以访问封闭类的私有成员,但不能反过来。

有没有人知道这样做的方法?

4 个答案:

答案 0 :(得分:4)

有几种可能性,其中两种是:

  1. 将所有这些类放在一个项目中并构建构造函数internal。其他项目将无法调用那些构造函数,但该项目中的代码可以。
  2. 创建这些类protected(而不是private)的构造函数,并在包含工厂方法的类中创建私有派生类。创建该私有类的实例并将其返回。
  3. 第二个选项的示例:

    public static class AnimalFactory
    {
        public static Animal Create(int parameter)
        {
            switch(parameter)
            {
                case 0:
                    return new DogProxy();
                case 1:
                    return new CatProxy();
                default:
                    throw new ArgumentOutOfRangeException("parameter");
            }
        }
    
        private class DogProxy : Dog { }
    
        private class CatProxy : Cat { }
    }
    
    public abstract class Animal { }
    
    public class Dog : Animal
    {
        protected Dog() { }
    }
    
    public class Cat : Animal
    {
        protected Cat() { }
    }
    

答案 1 :(得分:1)

当Daniel发布他的回答时,这是我正在处理的示例代码。看起来它正在做他建议的事情:

public static class BaseFactory
{
    public static Base Create(bool condition)
    {
        if (condition)
        {
            return Derived1.Create(1, "TEST");
        }
        else
        {
            return Derived2.Create(1, DateTime.Now);
        }
    }
}

public class Base
{
    protected Base(int value)
    {
    }

    protected static Base Create(int value)
    {
        return new Base(value);
    }
}

public sealed class Derived1: Base
{
    private Derived1(int value, string text): base(value)
    {
    }

    internal static Derived1 Create(int value, string text)
    {
        return new Derived1(value, text);
    }
}

public sealed class Derived2: Base
{
    private Derived2(int value, DateTime time): base(value)
    {
    }

    internal static Derived2 Create(int value, DateTime time)
    {
        return new Derived2(value, time);
    }
}

[编辑]以及丹尼尔的第二个建议:

public static class BaseFactory
{
    public static Base Create(bool condition)
    {
        if (condition)
        {
            return new Derived1Creator(1, "TEST");
        }
        else
        {
            return new Derived2Creator(1, DateTime.Now);
        }
    }

    private sealed class Derived1Creator: Derived1
    {
        public Derived1Creator(int value, string text): base(value, text)
        {
        }
    }

    private sealed class Derived2Creator: Derived2
    {
        public Derived2Creator(int value, DateTime time): base(value, time)
        {
        }
    }
}

public class Base
{
    protected Base(int value)
    {
    }

    protected static Base Create(int value)
    {
        return new Base(value);
    }
}

public class Derived1: Base
{
    protected Derived1(int value, string text): base(value)
    {
    }

    protected static Derived1 Create(int value, string text)
    {
        return new Derived1(value, text);
    }
}

public class Derived2: Base
{
    protected Derived2(int value, DateTime time): base(value)
    {
    }

    protected static Derived2 Create(int value, DateTime time)
    {
        return new Derived2(value, time);
    }
}

请注意,第二种方法意味着不幸的是,这些类无法被密封。

答案 2 :(得分:0)

不是使用类本身内部的方法作为工厂,而是通过静态类(“工厂”)实现Factory模式,该类根据您编写的逻辑返回正确的实例。

答案 3 :(得分:0)

您可以在基类构造函数中拦截派生类型创建,并使用Stack Frames检查调用者是否是您的工厂:

 protected Class1() //base class ctor
    {
        StackFrame[] stackFrames = new StackTrace().GetFrames(); 
        foreach (var frame in stackFrames)
        {
            //check caller and throw an exception if not satisfied
        }
    }