2014-02-28 35 views
3

请考虑这一点。我想创建一个创建动物的工厂(模式,而不是创造一个新的起源)。我以为我会聪明,创建具有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方法来创建鸟类,而不是抽象动物(不必为Bird写一个新的方法)。有没有一种方法可以指定Animal从Factorable继承,但是有它的后代用它自己的类型覆盖泛型T?

东西(这是愚蠢的代码,不工作)这样

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

也许我失去了一些东西,但一个'Animal'如何从自身'可分解'通用继承? – mclark1129

+1

@MikeC这在C#中是可行的。 – MarcinJuraszek

回答

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>(); 

UPDATE

阅读你的评论这是我的理解它后创建的实例的类型。它只知道它是动物或动物派生的类。那么,这个怎么样:

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>设置它提供了简单的方法,以确保输出类型是动物或派生。

用法:

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

工厂创建高级对象,允许其他需要它的类创建抽象类型。不过,它应该允许您将后代类类型注入已完成的层次结构中。这是我的代表的原因。假设我有一个图书馆来处理一个有Cage类的动物园。笼子使用工厂创造动物。 AnimalHandler类也是如此。整个库完成并密封在一个DLL中。现在我想创建一个Aviary应用程序。理想情况下,有一种方法可以告诉工厂:好吧,不要创建动物,请仅创建鸟类(我的代理人)。 – cockypup

+0

更新了我的答案。请注意,变量'b'仍然是'Animal'类型,但是拥有'Bird'类的实例。这是你想要的吗? –

+0

酷!这正是我所期待的。绿色复选标记为你。 – cockypup

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();