2011-07-26 108 views
3

我有一个XML解析器,它将解析17个不同的XML文档(我简化了这一点)。 当解析器完成其作业时,它会调用执行请求的对象。调用委托的数据提供者:细节还是泛型?

首先方式

,看起来像

- (void)didReceiveObject:(NSObject *)object ofType:(MyObjectType)type 

与MyObjectType是枚举的单一方法。

在这种方法中,我检查类型并将对象重定向到相应的方法。

方式二

没有为每个所述17种对象的可以接收的回调方法。

- (void)didReceiveFoo:(MYFoo *)foo 
- (void)didReceiveBar:(MYBar *)bar 
... and so on 

哪种使用代表的方式会更好? 我们和一位同事讨论过这个问题,并且找不到比另一个更有吸引力的方法。它似乎只是决定从解析器或委托内部调用什么方法......

即使在考虑添加未来方法/委托回调时,我们也没有看到任何实际问题。

其中一种方式比其他方式更好吗?有另一种方法吗?

回答

1

第一种方法:

优点:

  • 对未来的变化更灵活。

缺点:

  • 可能导致大的switch语句或混乱,如果...否则,如果... else语句。
  • 反正可能会导致一系列明确的方法。
  • 需要类型转换。

方法二:

优点:

  • 没有类型转换。
  • 如果方法是可选的,代表只困扰与它感兴趣的对象

缺点:

  • 如果方法是不可选的,并且界面后扩大,所有的代表将警告直到实施新方法。
  • 如果方法不是可选的,那么可以为每个委托实现很多方法。

通常,在构建委托接口时,我倾向于泛型以便将来可扩展。更改API,特别是使用开源代码,可能非常困难。另外,我不太明白为什么你有一个XML解析器做了这么多。你可能想要考虑一个不同的设计。 17个不同的XML文档看起来很多。除此之外,我会提出第三种方法。

第三种方法:

创建一个映射字符串块一本字典。这些块可能是void(^BlockName)(id obj)类型。您的解析器将定义一系列字符串,这些字符串将成为您各种块的关键字。例如,

NSString * const kFooKey = @"FooKey"; 
NSString * const kBarKey = @"BarKey"; 
// And so on... 

谁创建的XML解析器将注册自己感兴趣的每个键块。他们只需要为他们感兴趣的键注册,而且完全灵活地应对未来的变化。由于您正在注册显式的键/对象,因此可以在不进行类型转换的情况下断言传入的类型(实质上为Design By Contract)。这可能会因为你想要的而被杀死,但是我发现类似的设计在我的代码中非常有用。它结合了您的两种解决方案的优点。主要的缺点是如果你想使用没有块的SDK。但是,块已成为Objective-C的事实标准。

除此之外,如果您尚未这样做,您可能需要定义一个包含17个对象的常用功能的协议。这会将您的区块类型更改为void(^BlockName)(id<YourProtocol> obj)

+0

我真的很喜欢你的想法。对不起,我没有说明我们必须坚持使用iOS3。我会再次检查,我们只能去iOS4 +,但上次是没有。 – teriiehina

2

为什么不

- (void)didReceiveObject:(NSObject *)object 

去,然后检查类的类型?

这对我来说似乎更清洁和更具可扩展性,因为这意味着您可以在未来添加更多回调的情况下解析其他对象。

(我知道这是一样的选项之一,但我想指出的是您的第二个参数是不必要的。)

+0

我第二个这个。这里主要的好处是,如果不同类型之间有共同的工作,你可以把它收集在一个地方,并保持干爽。 –

+0

我不确定这是相同的,因为使用枚举告诉你可能会收到的所有类。如果我们以这种方式使用,那么我们将不得不在其他地方指定您应该测试的类。 主要观点是:我们想给出有关对象类型的信息:我们是否应该在方法的名称或参数中指定它。 – teriiehina

0

这是决定。

我们将实施这两种方法,看看哪种方式更多使用。

第一种方法是最简单和最快的,所以我们会保持它的内部需求。

但是,我们可能会将此代码作为静态库提供,因此我们希望提供最少量的信息。所以我们也会坚持第二种方式。

由于每个回调应该有一大块代码,通用的方式肯定是rbrown指出的大开关语句。

谢谢你的帮助。