Objective-C类别==访客模式?

时间:2009-08-26 13:35:12

标签: objective-c categories visitor

您是否认为Objective-C类别是visitor design pattern的实现?

2 个答案:

答案 0 :(得分:12)

不,Objective-C类别不是访问者模式的实现。类别在设计模式世界中确实没有完全匹配,因为在大多数语言中都不可能将方法注入到没有子类的现有类中。我会说它更接近decorator pattern,但是这种模式通常是用合成来实现的,即通过包装你想要“增强”的对象的实例。

访问者模式对于封装可应用于各种对象,结构等的算法逻辑非常有用。例如,如果要为对象图创建HTML输出,则可以(A)编写{每个对象上的{1}}方法并为每个对象调用它,或者(B)使用访问者模式并创建一个具体的访问者,知道如何为其访问的每个节点生成HTML输出。

前一种方法更通用,任务T的逻辑分散在X,Y和Z类的小块中。后一种方法将所有相关代码放在一个访问者对象中,这有助于简化维护和防止“我忘记了一堂课......”的问题。然而,对于简单的情况,访问者模式可能有些笨拙 - 当你有几个不同的并行功能并且希望从执行功能的类中抽象逻辑时,它真正得到回报。例如,您可以实现生成PDF或RTF输出等的其他访问者。每个访问者可以按照必要的顺序处理递归并调用自己的访问方法,并且单独的访问者可以使用完全不同的顺序。

应该注意的是,在许多语言中,访问者模式使用方法重载(相同名称,不同的签名/参数)。由于Objective-C不允许方法重载,因此必须使用不同的方法名称,但这实际上可以帮助避免因不知道调用哪些重载而导致的错误。

答案 1 :(得分:2)

类别可用于实现访客模式。

@protocol Visit
- (void)acceptVisitor:(MyVisitor *)visitor;
@end

@interface Foo (Visit) <Visit>
@end

@interface Bar (Visit) <Visit>
@end

@implementation MyVisitor

- (void)visit:(id)someObject {
    if ([someObject conformsToProtocol:@protocol(Visit)]) {
        [(id<Visit>)someObject acceptVisitor:self];
    }
}

- (void)visitFoo:(Foo *)foo { ... }

- (void)visitBar:(Bar *)bar { ... }

@end

@implementation Foo (Visit)
- (void)acceptVisitor:(MyVisitor *)visitor {
    [visitor visitFoo:self];
} 
@end

@implementation Bar (Visit)
- (void)acceptVisitor:(MyVisitor *)visitor {
    [visitor visitBar:Self];
}
@end

这是IMO比经典的GoF Visitor设计更整洁,因为访问类的公共接口没有污染,整个事情可以封装在访问者类的编译单元中。