调用委托的数据提供者:具体还是通用?

Posted

技术标签:

【中文标题】调用委托的数据提供者:具体还是通用?【英文标题】:Data provider calling a delegate: specifics or generic? 【发布时间】:2011-07-26 14:55:05 【问题描述】:

我有一个 XML 解析器,它将解析 17 个不同的 XML 文档(我正在简化它)。 当解析器完成其工作时,它会调用发出请求的对象。

第一种方式

一个看起来像的方法

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

其中 MyObjectType 是一个枚举。

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

第二种方式

我可以接收的17种对象中的每一种都有一个回调方法。

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

哪种方式使用委托会更好? 我们与一位同事就此进行了讨论,找不到比另一种更有吸引力的方法。似乎它只是决定从解析器或委托中调用什么方法....

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

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

【问题讨论】:

【参考方案1】:

为什么不去

- (void)didReceiveObject:(NSObject *)object

然后检查类类型?

这对我来说似乎更简洁,更可扩展,因为这意味着您将来可以解析其他对象而无需添加更多回调。

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

【讨论】:

我支持这个。这里的主要好处是,如果不同类型之间有任何共同的工作,您可以将其收集在一个地方并保持 DRY。 我不确定这是否相同,因为使用枚举会告诉您您可能收到的所有课程。如果我们要以这种方式使用,我们将不得不在其他地方指定您应该测试哪些类。要点是:我们要提供有关对象类型的信息:我们应该在方法名称中还是在其参数中指定它。【参考方案2】:

第一种方法:

优点:

更灵活地应对未来的变化。

缺点:

可能导致较大的 switch 语句或混乱的 if ... else if ... 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)

【讨论】:

我真的很喜欢你的想法。很抱歉,我没有指定我们必须坚持使用 ios3。我会再次确认我们只能使用 iOS4+,但上次没有。【参考方案3】:

这是决定。

我们将同时实现这两种方式,看看哪种方式更常用。

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

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

由于每个回调都应该有一大块代码,所以通用的方式肯定是 rbrown 指向的大 switch 语句。

感谢您的帮助。

【讨论】:

以上是关于调用委托的数据提供者:具体还是通用?的主要内容,如果未能解决你的问题,请参考以下文章

Spring实战之切面编程

代理模式

直接与委托 - jQuery .on()

Asp.net 委托

事件与委托深入理解

协议与委托