编写工厂方法时,我可以使用
Activator.CreateInstance
或具有静态抽象方法的接口,如下所示。
这里有我必须考虑的优点和缺点吗?
Activator.CreateInstance
using System;
var s = Factory<Student>("Anton");
s?.Print();
var t = Factory<Teacher>("Howard");
t?.Print();
Person? Factory<T>(string name)
where T : Person
{
return (T?)Activator.CreateInstance(typeof(T), name);
}
class Person
{
public string Name { get; set; }
public Person(string name) => Name = name;
public void Print() => Console.WriteLine(Name);
}
class Student : Person
{
public Student(string name) : base($"Student: {name}") { }
}
class Teacher : Person
{
public Teacher(string name) : base($"Teacher: {name}") { }
}
using System;
var s = Factory<Student>("Anton");
s.Print();
var t = Factory<Teacher>("Howard");
t.Print();
Person Factory<T>(string name)
where T : Person, IPerson<T>
{
return T.Constructor(name);
}
interface IPerson<T>
{
static abstract T Constructor(string name);
}
class Person : IPerson<Person>
{
public string Name { get; set; }
public Person(string name) => Name = name;
public void Print() => Console.WriteLine(Name);
public static Person Constructor(string name) => new(name);
}
class Student : Person, IPerson<Student>
{
public Student(string name) : base($"Student: {name}") { }
static Student IPerson<Student>.Constructor(string name) => new(name);
}
class Teacher : Person, IPerson<Teacher>
{
public Teacher(string name) : base($"Teacher: {name}") { }
static Teacher IPerson<Teacher>.Constructor(string name) => new(name);
}
两种方法都是恕我直言的糟糕设计,因为它们完全忽略了泛型的含义:编译时的类型安全。那么写下来有什么好处
var s = Factory<Student>("Anton");
或
var s = IPerson<Student>.Create("Anton");
结束
var s = new Student("Anton");
?
在所有三种情况下,您都需要知道编译时的类型,因此这两者之间没有太大区别。静态接口方法的唯一好处是,在更改
Constructor
方法的签名时可以获得编译器支持。但毕竟,接口不应该对如何创建实例做出任何假设。接口定义功能。
另一方面,只有当您不在编译时知道类型,或者您想向客户端隐藏它们时,工厂才有意义,例如:
var s = myFactory.Create("Anton");
通过这种方式,工厂决定实例化哪种类型。另一方面,客户端只是获得一个抽象,即接口指针(例如
IPerson
)。