2009-08-26 7 views

答えて

11

いいえ、Objective-Cカテゴリはビジターパターンの実装ではありません。ほとんどの言語では、サブクラスを持たない既存のクラスにメソッドを挿入する手法は不可能なため、カテゴリはデザインパターンの世界で完全に一致するわけではありません。私はそれがdecorator patternに近いと言っていますが、そのパターンは通常、構成を使用して、つまり「強化する」オブジェクトのインスタンスをラップすることによって実装されます。

visitorパターンは、さまざまなオブジェクト、構造体などに適用できるアルゴリズムロジックをカプセル化するのに便利です。たとえば、オブジェクトグラフのHTML出力を作成する場合、(A) (B)visitorパターンを使用して、訪問する各ノードのHTML出力を生成する方法を知っている具体的な訪問者を作成します。

前者のアプローチはより一般的であり、タスクTのロジックはクラスX、Y、Z間の小さなチャンクに散在しています。後者のアプローチでは、すべての関連するコードを単一のビジターオブジェクトに配置します。 "私はそのクラスを忘れてしまった..."という問題を防ぐ。しかし、訪問者のパターンは単純な状況では多少重いものですが、いくつかの異なる並行機能があり、機能が実行されているクラスからロジックを抽象化したいときには本当に効果的です。たとえば、PDFやRTF出力などを生成する他の訪問者を実装することができます。各訪問者は再帰を処理し、必要な順序で独自の訪問メソッドを呼び出すことができ、別々の訪問者は完全に異なる順序を使用できます。

多くの言語では、訪問者パターンはメソッドオーバーロード(同じ名前、異なる署名/引数)を使用することに注意してください。 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のビジターデザインよりもIMO滑らかな印象です。