2

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 (...)
    {
        ...
    }
}

我应该使用枚举“类型”作为嵌入在 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 (...)
    {
        ...
    }
}

投票已开启!

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

4

5 回答 5

1

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

您可以:

于 2009-06-02T09:29:59.063 回答
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);
    }
}

(编辑)

当然,这只有在你有一个具体的PetDescritor:CatDescriptorDogDescriptor.

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

或者,您可以EnumFactory 类中声明一个指定Pet您喜欢创建的具体内容的类。维基百科有一个简单的Pizza示例。

于 2009-06-02T10:02:37.327 回答
0

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

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

于 2009-06-02T09:30:55.240 回答
0

你不想有一个工厂类,你想为每个宠物类型都有工厂类。

它们都应该实现一个 Pet 工厂接口。

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

或者,每个宠物类都可以负责创建自己的实例(或链接到宠物的宠物描述符。看看工厂方法模式:

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

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

至少这是我的理解。

于 2009-06-02T09:37:07.583 回答
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# 自动扫描工厂

于 2013-06-17T17:21:47.267 回答