我经常使用类工厂模式,其中类具有私有构造函数和静态方法来创建类。这允许由于某种原因无法构造类的情况,并返回null - 非常方便。
我希望能够将其扩展为工厂方法,该方法根据条件从派生类的层次结构中创建特定类。但是,我无法看到隐藏派生类的构造函数以强制使用工厂方法的方法。如果工厂方法在基类中,则它不再能够访问派生类的私有构造函数。将工厂方法放在每个派生类中都不起作用,因为必须事先知道所需的类型。如果一个类可以访问嵌套类的私有成员,嵌套类可能是一种方式,但遗憾的是,嵌套类似乎可以访问封闭类的私有成员,但不能反过来。
有没有人知道这样做的方法?
答案 0 :(得分:4)
有几种可能性,其中两种是:
internal
。其他项目将无法调用那些构造函数,但该项目中的代码可以。protected
(而不是private
)的构造函数,并在包含工厂方法的类中创建私有派生类。创建该私有类的实例并将其返回。第二个选项的示例:
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
}
}