Objective C – 根据types从基类创build具体的类实例

为了给一个真实世界的例子,说基类是车辆和具体类是TwoWheeler和FourWheeler。 现在,这辆车的型号是TwoWheeler还是FourWheeler,是由基地车决定的。 当我使用alloc-init方法创buildTwoWheeler / FourWheeler的一个实例时,它会调用像下面这样的超级实现来设置Vehicle类中定义的公共属性的值,并且在这些属性之外,其中一个是实际决定types的types是TwoWheeler或FourWheeler。

if (self = [super initWithDictionary:dict]){ [self setOtherAttributes:dict]; return self; } 

现在,当我收到车辆时,其中一些可能是TwoWheeler,另外一些则是FourWheeler。 因此,我不能直接创buildTwoWheeler或FourWheeler的实例

 Vehicle *v = [[TwoWheeler alloc] initWithDictionary:dict]; 

有什么办法可以创build一个基类的实例,一旦我知道types,根据types创build一个子类的实例并返回它。 随着目前的实施,这将导致无限循环,因为我称之为超级实现从具体类。

当我不知道哪个具体的类应该事先被实例化时,处理这个场景的完美devise是什么?

一般来说,这是用工厂完成的。

如果你希望工厂成为基类的一部分,那很好,但是将来可能会引起问题。 在Objective C中,类方法可以创build好的工厂。

 + (Vehicle *)vehicleWithDictionary:(NSDictionary *)dict { if ([[dict objectForKey:kVehicleType] isEqualToString:@"TwoWheeler"]) { return [[[TwoWheeler alloc] initWithDictionary:dict] autorelease]; } else if ([[dict objectForKey:kVehicleType] isEqualToString @"FourWheeler"]) { return [[[FourWheeler alloc] initWithDictionary:dict] autorelease]; } else { return [[[Vehicle alloc] initWithDictionary:dict] autorelease]; } } 

工厂可以是车辆类的一部分,并且可以这样使用。

 // Instead of [[Vehicle alloc] initWithDictionary:dict] Vehicle *vehicle = [Vehicle vehicleWithDictionary:dict]; 

更新

我想出了一个方法去做所要求的。 让它成为一个光辉的例子,说明为什么这是一个坏主意,为什么你永远不应该这样做。

 - (id)initWithDictionary:(NSDictionary *)dict { self = [super init]; if (self) { // If override is in the dictionary, then it mustn't try to call the subclass. if (![dict objectForKey:kOverride]) { NSMutableDictionary *overrideDict = [NSMutableDictionary dictionaryWithDictionary:dict]; [overrideDict setObject:@"override" forKey:kOverride]; if ([[dict objectForKey:kVehicleType] isEqualToString:@"TwoWheeler"]) { [self release]; return [[[TwoWheeler alloc] initWithDictionary:overrideDict] autorelease]; } else if ([[dict objectForKey:kVehicleType] isEqualToString @"FourWheeler"]) { [self release]; return [[[FourWheeler alloc] initWithDictionary:overrideDict] autorelease]; } } // init as normal } return self; } 

你应该使用抽象工厂如下,类Vehicle将有一个方法称为createInstance,这个方法将有一个参数,将决定创build什么考虑例子

 + (Vehicle*) createInstance:(int)numberOfWheels { if(numberOfWheels == 2) { return [[TwoWheeler alloc] init]; } else { return [[FourWheeler alloc] init]; } return nil; } 

你会这样称呼它

 Vehicle *v = [Vehicle createInstance:2];