使用工厂时的反思成本

时间:2009-06-02 09:25:25

标签: c# performance reflection factory

stackoverflow的好人,

与往常一样,我正在编写工厂以动态实例化对象。

要进行模式化,我有四种类型:

class CatDescriptor : PetDescriptor
class DogDescriptor : PetDescriptor

class Cat : Pet
class Dog : Pet

我从工厂实现了最后两种类型。这就是困境: 我是否应该使用“is”运算符测试描述符类型,该运算符隐藏反射然后花费一些东西。

static Pet.Factory(PetDescriptor descriptor)
{
    if (descriptor is CatDescriptor)
    {
        return new Cat();
    }
    else if (...)
    {
        ...
    }
}

我应该使用Enum“Type”作为PetDescriptor中嵌入的属性。

class PetDescriptor
{
    public Type PetType;

    public enum Type
    {
        Cat,
        Dog
    }
}

static Pet.Factory(PetDescriptor descriptor)
{
    switch (descriptor.PetType)
    {
        case PetDescriptor.Type.Cat:
            return new Cat();
        ....
    }
}

或使用虚拟方法:

class PetDescriptor
{
    public virtual bool IsCat()
    {
        return false;
    }

    ...
}

class CatDescriptor : PetDescriptor
{
    public override bool IsCat()
    {
        return true;
    }
}

static Pet.Factory(PetDescriptor descriptor)
{
    if (descriptor.IsCat())
    {
        return new Cat();
    }
    else if (...)
    {
        ...
    }
}

投票已经开启!

编辑:问题是关于反射性能,而不是工厂设计。

5 个答案:

答案 0 :(得分:1)

在您的工厂进行测试会失败的目的(您必须为要创建的每个新具体实例更新您的类。)

你可以:

答案 1 :(得分:1)

由于您的PetDescriptor标识Pet,我会使用重载

static class PetFactory
{
    public static Dog CreatePet(DogDescriptor descriptor)
    {
        return new Dog(descriptor);
    }

    public static Cat CreatePet(CatDescriptor descriptor)
    {
        return new Cat(descriptor);
    }
}

(适用编辑)

当然,这仅适用于具体PetDescritorCatDescriptorDogDescriptor

如果您在创建时没有 abstract PetDescriptor,我会选择第一个解决方案。

或者,您可以在工厂类中声明Enum,并指定您要创建的具体PetWikipedia有一个Pizza的简单示例。

答案 2 :(得分:0)

你的第三个解决方案(使用虚方法)肯定是不对的:PetDescriptor类不应该知道它的所有派生类(每次创建XXXDescriptor类时都必须添加一个新方法IsXXX。)

我认为你的第一个解决方案是最好的。枚举不会添加任何有用的东西,它只会强制您在描述符类中添加更多代码

答案 3 :(得分:0)

您不希望拥有一个工厂类,您希望每个Tyep都有一个因子类。

他们都应该实现Pet工厂界面。

每次添加新宠物时,您都必须编辑宠物工厂,而不是仅仅创建一个新的宠物工厂类并使用它。

或者每个宠物类可以负责创建自己的实例(或者与宠物相关联的宠物描述符。看看Factory方法模式:

http://en.wikipedia.org/wiki/Factory_method_pattern

http://www.dofactory.com/Patterns/PatternFactory.aspx

至少这是我的理解。

答案 4 :(得分:0)

我的英语很糟糕,所以我希望我能正确理解你的问题。

你有多少宠物型?

如果你有2只宠物,并且你确定它的数量将来不会增加 - 不要使用任何工厂(不要狂热)

如果有10只宠物的东西 - 我想你需要像抽象工厂这样的东西。 在这种情况下 - 每个描述符可以创建自己的宠物,所以如果你有任何描述符,你可以创建一些宠物没有任何附加信息:

 //of course u can use your own base class instead of interface. 
interface IPetDescriptor
{
   //here u can place some additional type information, if u need. Tags or genetic code, or maybe some story about this type
    Pet CreatePet();//Maybe u need some aditional createInformation?

}

class DogDescriptor:IPetDescriptor
{
   public Pet CreatePet(){ return new Dog();}
}
class CatDescriptor:IPetDescriptor
{
   public Pet CreatePet(){ return new Cat();}
}

 class Pet
 {
    public Pet static Pet.Factory(IPetDescriptor descriptor)
    {
       //Place for additional initialization, if u need...


       //we don't care about pet type. Thats good.
       return descriptor.CreatePet(); 
     }
     .... 
 }

如果有100种宠物类型,更好的解决方案是使用IoC框架,或编写自己的 (例如,你可以创建类型自动搜索器):

C# Auto-scaning factory