数据提供者调用委托:细节还是通用?
我有一个 XML 解析器,它将解析 17 个不同的 XML 文档(我正在简化它)。 当解析器完成其工作时,它会调用执行请求的对象。
第一种方法
单一方法,看起来像
- (void)didReceiveObject:(NSObject *)object ofType:(MyObjectType)type
MyObjectType 是一个枚举。
在此方法中,我检查类型并将对象重定向到相应的方法。
第二种方式
对于我可以接收的 17 种类型的对象,每一种都有一个回调方法。
- (void)didReceiveFoo:(MYFoo *)foo
- (void)didReceiveBar:(MYBar *)bar
... and so on
哪种方式使用委托会更好? 我们与一位同事对此进行了讨论,但找不到一种比另一种更有吸引力的方法。看起来它只是决定从解析器或委托中调用什么方法......
即使在考虑添加未来的方法/委托回调时,我们也没有看到任何真正的问题。
这些方法中的一种比另一种更好吗?还有别的办法吗?
I have a XML parser which will parse 17 different XML documents (I'm simplifying this).
When the parser has finished its job, it calls the object that did the request.
First way
A single method that looks like
- (void)didReceiveObject:(NSObject *)object ofType:(MyObjectType)type
with MyObjectType being an enum.
In this method, I check the type and redirect the object to the corresponding method.
Second way
There is a callback method for each of the 17 types of object I can receive.
- (void)didReceiveFoo:(MYFoo *)foo
- (void)didReceiveBar:(MYBar *)bar
... and so on
Which way of using delegates will be better?
We had a discussion about this with a colleague and couldn't find one way more appealing than another. It seems like it's just deciding what method to call from the parser or within the delegate....
Even when thinking about adding future methods/delegates callbacks, we don't see any real problem.
Is one of these ways better than the other? Is there another way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么不先
检查类类型呢?
对我来说,这看起来更干净、更可扩展,因为这意味着您将来可以解析其他对象,而无需添加更多回调。
(我知道这与选项一相同,但我想指出你的第二个论点是不必要的。)
Why not go with
and then inspect the class type?
This seems cleaner and more extensible to me, because it means you can parse other objects in the future without adding more callbacks.
(I know this is the same as option one, but I wanted to point out that your second argument was unnecessary.)
第一种方法:
优点:
缺点:
第二种方法:
优点:
缺点:
一般来说,在构建委托接口时,我倾向于泛型以实现未来的可扩展性。更改 API,尤其是使用开源代码,可能非常困难。另外,我不太明白为什么让一个 XML 解析器做这么多事情。您可能需要考虑不同的设计。 17 个不同的 XML 文档看起来很多。除此之外,我将提出第三种方法。
第三种方法:
创建一个将字符串映射到块的字典。这些块可能是
void(^BlockName)(id obj)
类型。您的解析器将定义一系列字符串,它们将成为各个块的键。例如,无论谁创建 XML 解析器,都会为他们感兴趣的每个键注册一个块。他们只需要注册他们感兴趣的键,并且对未来的更改完全灵活。由于您正在注册显式键/对象,因此您可以断言传入的类型而无需进行类型转换(本质上是 Design By合同)。对于你想要的东西来说,这可能有点过头了,但我发现类似的设计在我的代码中非常有用。它结合了两种解决方案的优点。它的主要缺点是如果您想使用没有块的 SDK。然而,块正在成为 Objective-C 事实上的标准。
除此之外,如果您还没有这样做,您可能需要定义一个包含 17 个对象的通用功能的协议。这会将您的块类型更改为
void(^BlockName)(idobj)
。First method:
Pros:
Cons:
Second method:
Pros:
Cons:
Generally when building delegate interfaces I lean towards generics for future extensibility. Changing an API, especially with open source code, can be very difficult. Also, I don't quite understand why you have one XML parser doing so much. You may want to consider a different design. 17 different XML documents seems like a lot. That aside, I'll propose a third method.
Third method:
Create a dictionary that maps strings to blocks. The blocks would probably be of type
void(^BlockName)(id obj)
. Your parser would define a series of strings that will be the keys for your various blocks. For example,Whoever creates the XML parser would register a block for each key they are interested in. They only need to register for the keys they are interested in and it's completely flexible to future change. Since you are registering for explicit keys/objects, you can assert the passed in type without a type cast (essentially Design By Contract). This might be over kill for what you want, but I've found similar designs very beneficial in my code. It combines the pros of both of your solutions. It's main downfall is if you want to use an SDK that doesn't have blocks. However, blocks are becoming a de facto standard with Objective-C.
On top of this you may want to define a protocol that encompasses the common functionality of your 17 objects, if you haven't done so already. This would change your block type to
void(^BlockName)(id<YourProtocol> obj)
.这是决定。
我们将同时实现这两种方式,看看哪种方式更常用。
第一种方法是最简单、最快的,因此我们将保留它以满足内部需求。
但我们可能会将此代码作为静态库提供,因此我们希望提供最少量的信息。所以我们也将坚持第二种方式。
由于每个回调都应该有一大块代码,因此通用方法肯定是 rbrown 指出的大 switch 语句。
感谢您的帮助。
Here's the decision.
We will implement both and see which way is the more used.
The first way is the easiest and fastest so we will keep it for internal needs.
But we may be shipping this code as a static library so we want to give the minimal amount of information. So we will also stick with the with the second way.
As there should be a big chunk of code for each callback, the generic way will certainly be the big switch statement rbrown pointed.
Thank you for your help.