一劳永逸地使用泛型实现工厂模式

时间:2014-02-28 19:07:21

标签: c# oop generics inheritance

考虑一下。我想创造一个创造动物的工厂(模式,而不是一个新的起源)。我认为我会很聪明,并且创建一个具有我需要的3件事的课程,

  • 返回抽象动物的代表
  • 为每只动物返回特定动物的创建方法
  • 使用委托
  • 的每个创建方法的实例

厌倦了再次这样做并且每次我需要使用工厂模式时获得,我认为我会更加聪明并且一劳永逸地解决它。所以,我创造了这个漂亮的课程

class Factorable<T> where T: class, new() 
{
    delegate T CreateDelegate();
    static CreateDelegate DoCreate = new CreateDelegate (CreateSelf);
    static T CreateSelf()
    {
        return new T();
    }
}

class Factory<T> where T : Factorable<T>
{
    public Factorable<T>.CreateDelegate CreationMethod ;
} 

我想,很酷,我可以让顶级(动物)继承自这个类,所以我不必为所有动物编写和实例化所有特定的创建方法。一切都归功于仿制药。差不多......看到这个:

class Animal:Factorable<Animal> {...}
class Bird:Animal {...}

Factory genesis = new Factory<Animal>();
genesis.CreationMethod = Animal.DoCreate;
Animal instance = genesis.CreateAnimal();  //instance is a brand new abstract Animal

genesis.CreationMethod = Bird.DoCreate;  //lets make it create birds!
instance = genesis.CreateAnimal();  // wrong, instance is still an abstract Animal

有什么方法可以解决这个问题吗?我想要Bird继承的CreateSelf方法来创建Birds,而不是抽象动物(不必为Bird编写新方法)。有没有办法指定Animal继承自Factorable但是它的后代要用自己的类型覆盖泛型T?

某事(这是愚蠢的代码,不起作用)就像这样

class Animal:Factorable<Animal... or better the actual type of the class that has inherited>

2 个答案:

答案 0 :(得分:3)

你不是有点过于复杂吗?假设Animal是您的基类:

public class Factory
{
    public static T Create<T>() where T : Animal, new()
    {
        return new T();
    }
}

用法:

var a = Factory.Create<Animal>();
var b = Factory.Create<Bird>();

<强>更新

阅读完评论后,我就是这样理解的:调用工厂的对象不知道所创建实例的确切类型。它只知道它是Animal或Animal派生的类。那么,这个怎么样:

public class Factory
{
    private Type _outputType = typeof(Animal);

    public void Produces<T>() where T : Animal, new()
    {
        _outputType = typeof(T);
    }

    public Animal CreateAnimal()
    {
        return (Animal)Activator.CreateInstance(_outputType);
    }
}

注意:将输出类型设为私有并使用Produces<T>设置它可以轻松确保输出类型为Animal或派生类型。

用法:

var f = new Factory();  // factory produces animals
var a = f.CreateAnimal();
f.Produces<Bird>();     // from now on factory produces birds
var b = f.CreateAnimal();

答案 1 :(得分:0)

使用静态方法无法做到这一点。试试这个:

class Factorable<T> where T: class, new() 
{
    delegate T CreateDelegate();
    CreateDelegate DoCreate = new CreateDelegate (CreateSelf);
    T CreateSelf()
    {
        return new T();
    }
}
class Animal : Factorable<Animal>...
...
Factory genesis = new Factory();
genesis.CreateAnimal = (new Animal()).DoCreate;
Animal instance = genesis.CreateAnimal(); 

genesis.CreateAnimal = (new Bird()).DoCreate;
instance = genesis.CreateAnimal();