在objective-c中创建对象工厂的最佳方法是什么?

时间:2011-03-23 14:59:16

标签: objective-c class factory registration

我有这样的类层次结构:

MyBox
  |
  |->ImageBox
  |->GalleryBox
  |->MovieBox
  |-> ...

每个字符串都由像@“image-box”或@“gallery-box”这样的字符串标识来自xml块,如下所示: <image-box><property1>value1</property1>...</image-box>。 所以我决定创建一个工厂类,它可以为我创建给定xml块的正确对象:

[BoxFactory.h]
@interface BoxFactory {
    NSMutableDictionary* stringToClassMapping;
}
+(BoxFactory)sharedBoxFactory;
-(void)registerClass:(Class)clazz withKey:(NSString*)key;
-(MyBox*)getBoxFromXml:(NSString*)xmlBlock;
@end


[.m]
#import "BoxFactory.h"
#import "MyFantasticXmlLibrary.h"
BoxFactory* gInstance=nil;
@implementation BoxFactory
+(BoxFactory*)sharedBoxFactory {
    if (gInstance==nil)
        gInstance=[[BoxFactory alloc]init];
    return gInstance;
}
-(id)init {
    self=[super init];
    stringToClassMapping=[[NSMutableDictionary alloc]initWithCapacity:10];
    return self;
}
-(void)registerClass:(Class)clazz withKey:(NSString*)key {
    [stringToClassMapping setObject:clazz forKey:key];
}
-(MyBox*)getBoxFromXml:(NSString*)xmlBlock {
    NSString* key=[MyFantasticXmlLibrary getRootNodeName:xmlBlock];
    return [[[stringToClassMapping objectForKey:key]alloc]initWithXml:xmlBlock];
}
@end

现在的问题是:具体类应该在哪里调用registerClass:withKey:方法?似乎正确的位置将在BoxFactory的init方法中,但这意味着必须为每个添加的类修改Factory,这对于大型层次结构是不可扩展的。

我真的想找到一种方法将注册调用放在具体类本身,保持更好的组织代码和更少的依赖。但是直到现在我还没有找到一种方法来在加载类时执行代码,而没有init它的实例。

2 个答案:

答案 0 :(得分:1)

好的,我在发布问题后5分钟发现了它,但我仍然认为它可以帮助某人,所以我会把它留在这里:

在执行开始时,在图像中加载类时,NSObject中有一个方法+(void)load。因此,在工厂中注册类的最佳位置是具体类本身的+(void)load方法。例如:

@implementation ImageBox
+(void)load {
    [[BoxFactory sharedBoxFactory]registerClass:[ImageBox class] withKey:@"image-box"];
}
-(id)initWithXmlBlock:(NSString*)xmlBlock {
[...]

答案 1 :(得分:1)

我有一些想法:

选项1:更改XML

如果您可以控制文件格式,则可以使用NSClassFromString使Objective-C类以这种方式工作。

选项2:将注册信息存储在.plist

如果存储标签的映射 - &gt;班级或班级 - &gt;在.plist中标记,您只需在启动时使用NSDictionary dictionaryWithContentsOfFile加载,而不是在代码中将其全部加载

选项3:面向属性的方法

通过类别或协议使用属性装饰类,这样您就可以在引导时查询对象模型并使用Type Introspection来发现可用的类及其标记。这避免了必须管理两件事(plist和类)并且还避免了必须更改xml(有时候是禁止的,因为它不是你的东西)。它在启动时有点沉重,但根据你的工作情况,它可能是一个很好的交易。