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 (...)
{
...
}
}
投票已经开启!
编辑:问题是关于反射性能,而不是工厂设计。
答案 0 :(得分:1)
在您的工厂进行测试会失败的目的(您必须为要创建的每个新具体实例更新您的类。)
你可以:
(更好)使用IoC框架为您设置对象(我建议Castle Windsor,NInject或者如果您只在MS商店,{{3 }})。
答案 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);
}
}
(适用编辑)强>
当然,这仅适用于具体PetDescritor
:CatDescriptor
或DogDescriptor
。
如果您在创建时没有 abstract PetDescriptor
,我会选择第一个解决方案。
答案 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框架,或编写自己的 (例如,你可以创建类型自动搜索器):