Objective-C中的访客模式 [英] Visitor Pattern in Objective-C

查看:152
本文介绍了Objective-C中的访客模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在寻找在Objective-C中实现Visitor设计模式的最佳方法。由于该语言不支持方法重载,因此可能在Java中找到的传统实现似乎是不可能的。

I've been looking at the best way to implement the Visitor design pattern in Objective-C. Since the language doesn't support method overloading, a 'traditional' implementation such as one might find in Java seems impossible.

在我当前的实现中,我有一个访问者协议,一个Visitor类,以及该Visitor类的几个子类,以及要访问的各种对象。一旦访问对象接受访问者,他们就会调用访问者的访问方法,将自己作为参数传递。 visit方法接受一个id,然后对它进行类型转换并调用

In my current implementation, I have a Visitor protocol, a Visitor class, and several subclasses of that Visitor class, along with the various objects to visit. Once a visited object accepts the Visitor, they call the visit method of the Visitor, passing themselves as an argument. The visit method takes an id, then type-casts it and calls

[self performTasksOnObjectClass: (ObjectClass *)object];

作为if / elseif / else块的一部分。这些调用是由相关的Visitor子类拾取的,访问者在对象上执行它需要的任何任务。

as part of an if/elseif/else block. These calls are them picked up by the relevant Visitor subclass and the Visitor performs whatever tasks it needs to on the object.

是否有更好的方法来实现访问者模式而不是这个?我不喜欢在if / elseif / else块中使用'isKindOfClass'或'isMemberOfClass'调用。它看起来很笨重而且不优雅。另外,以这种方式仍然值得实现Visitor方法吗?访问过的对象仍然可以不知道访问者,但还有其他方法可以实现这一点。

Is there a better way of implementing the Visitor pattern than this? I dislike resorting to 'isKindOfClass' or 'isMemberOfClass' calls inside if/elseif/else blocks. It just seems clunky and inelegant. Additionally, is it still 'worth' implementing a Visitor method in this way? The visited objects can still remain ignorant of the Visitor, but there are other ways in which this can be achieved.

已经有人建议委托或类集群可能更适合访客模式的替代方案。我有兴趣看看你们都在想什么!

It has already been suggested that either delegation or class clusters might be more suitable alternatives to the Visitor pattern. I'd be interested to see what you all think!

编辑:我实际上在子类中调用了不同名称的方法,我已经更清楚了。

I actually had differently named methods being called in the subclass, I've made this clearer.

推荐答案

你可以使用一些内省/反射来使它更清洁。你不能重载方法名,但你可以避免写这样的开关语句:

You can use some introspection/reflection to make this a bit cleaner. You can't overload method names but you can avoid writing a switch statement like this:

- (void)performTasks:(id)object
{
    Class class = [object class];
    while (class && class != [NSObject class])
    {
        NSString *methodName = [NSString stringWithFormat:@"perform%@Tasks:", class];
        SEL selector = NSSelectorFromString(methodName);
        if ([self respondsToSelector:selector])
        {
            [self performSelector:selector withObject:object];
            return;
        }
        class = [class superclass];
    }
    [NSException raise:@"Visitor %@ doesn't have a performTasks method for %@", [self class], [object class]];
}

您的实际performTasks方法将按以下方式命名:

Your actual performTasks methods would then be named as follows:

- (void)performFooTasks:(Foo *)foo
{
    //tasks for objects of class Foo
}

- (void)performBarTasks:(Bar *)bar
{
    //tasks for objects of class Bar
}

etc...

注意:如果你正在使用ARC,通过以这种方式从字符串创建选择器,您将得到虚假警告,因为它无法在编译时告诉方法参数应该保留规则。您可以使用#pragma静音这些警告,如下所示:

Note: If you're using ARC, you'll get spurious warnings by creating selectors from strings in this way because it can't tell at compile time what the retain rules should be for the method parameters. You can silence these warnings using a #pragma, as follows:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [self performSelector:selector withObject:object];
#pragma clang diagnostic pop

这篇关于Objective-C中的访客模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆