Sim*_*ton 12 design-patterns objective-c visitor ios
我一直在寻找在Objective-C中实现Visitor设计模式的最佳方法.由于该语言不支持方法重载,因此在Java中可能发现的"传统"实现似乎是不可能的.
在我当前的实现中,我有一个Visitor协议,一个Visitor类,以及该Visitor类的几个子类,以及要访问的各种对象.一旦访问对象接受访问者,他们就会调用访问者的访问方法,将自己作为参数传递.visit方法接受一个id,然后键入它并调用它
[self performTasksOnObjectClass: (ObjectClass *)object];
Run Code Online (Sandbox Code Playgroud)
作为if/elseif/else块的一部分.这些调用由相关的Visitor子类拾取,访问者执行对象所需的任何任务.
有没有比这更好的实现访客模式的方法?我不喜欢在if/elseif/else块中使用'isKindOfClass'或'isMemberOfClass'调用.它看起来很笨重而且不够优雅.另外,以这种方式实现Visitor方法还值得吗?访问过的对象仍然可以不知道访问者,但还有其他方法可以实现这一点.
已经有人提出,委托或类集群可能是访客模式的更合适的替代方案.我有兴趣看看你们都在想什么!
编辑:我实际上在子类中调用了不同的命名方法,我已经更清楚了.
Nic*_*ood 12
你可以使用一些内省/反射来使它更清洁.您不能重载方法名称,但可以避免编写如下的switch语句:
- (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]];
}
Run Code Online (Sandbox Code Playgroud)
然后,您的实际performTasks方法将按如下方式命名:
- (void)performFooTasks:(Foo *)foo
{
//tasks for objects of class Foo
}
- (void)performBarTasks:(Bar *)bar
{
//tasks for objects of class Bar
}
etc...
Run Code Online (Sandbox Code Playgroud)
注意:如果您正在使用ARC,则会通过以这种方式从字符串创建选择器来获得虚假警告,因为它无法在编译时告诉方法参数应该保留规则.您可以使用#pragma使这些警告静音,如下所示:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:selector withObject:object];
#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)