Objective-C分类 == 访问者模式?

6
2个回答

12
不,Objective-C类别不是访问者模式的实现。类别在设计模式世界中没有确切的匹配,因为在大多数语言中,将方法注入现有类别而不使用子类别的技术是不可能的。我认为它更接近于装饰器模式,但通常使用组合来实现该模式,即通过包装要“增强”的对象的实例。
访问者模式对于封装可应用于各种对象、结构等的算法逻辑非常有用。例如,如果您想为对象图创建HTML输出,则可以(A)在每个对象上编写htmlString方法并为每个对象调用它,或者(B)使用访问者模式并创建一个具体的访问者,该访问者知道如何为其访问的每个节点生成HTML输出。
前一种方法更通用,任务T的逻辑分散在X、Y和Z类的小块中。后一种方法将所有相关代码放在单个访问者对象中,这往往简化了维护并防止“我忘记了那个类……”问题。然而,访问者模式对于简单情况来说可能过于繁琐——当您有几个不同的平行功能并希望从执行功能的类别中抽象出逻辑时,它才真正有用。例如,您可能会实现其他访问者,它们会产生PDF或RTF输出等。每个访问者都可以处理递归并按必要的顺序调用自己的visit方法,而单独的访问者可以使用完全不同的顺序。

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


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

我认为这种设计比经典的 GoF 访问者模式更加简洁,因为它不会污染被访问类的公共接口,而且整个过程可以封装在访问者类的编译单元中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接