Objective-Cのカテゴリはビジターデザインパターンの実装だと思いますか?
2 に答える
いいえ、Objective-Cカテゴリはビジターパターンの実装ではありません。サブクラスなしで既存のクラスにメソッドを挿入する手法はほとんどの言語で不可能であるため、カテゴリはデザインパターンの世界では実際には完全に一致していません。デコレータパターンに近いと思いますが、そのパターンは通常、コンポジションで実装されます。つまり、「拡張」したいオブジェクトのインスタンスをラップすることによって実装されます。
ビジターパターンは、さまざまなオブジェクトや構造体などに適用できるアルゴリズムロジックをカプセル化するのに役立ちます。たとえば、オブジェクトのグラフのHTML出力を作成する場合は、(A)htmlString
各オブジェクトにメソッドを記述できます。オブジェクトごとに呼び出すか、(B)ビジターパターンを使用して、訪問するノードごとにHTML出力を生成する方法を知っている具体的なビジターを作成します。
前者のアプローチはより一般的であり、タスクTのロジックは、クラスX、Y、およびZに小さなチャンクに分散しています。後者のアプローチは、関連するすべてのコードを単一のビジターオブジェクトに配置します。これにより、メンテナンスが簡素化され、「Iその1つのクラスを忘れました...」問題。ただし、ビジターパターンは、単純な状況ではおそらくやや手間がかかります。実際に効果があるのは、いくつかの異なる並列機能があり、機能が実行されているクラスからロジックを抽象化したい場合です。たとえば、PDFやRTF出力などを生成する他の訪問者を実装できます。各訪問者は再帰を処理し、必要な順序で独自の訪問メソッドを呼び出すことができ、別々の訪問者は完全に異なる順序を使用できます。
多くの言語では、ビジターパターンはメソッドのオーバーロード(同じ名前、異なる署名/引数)を使用することに注意してください。Objective-Cではメソッドのオーバーロードが許可されていないため、個別のメソッド名を使用する必要がありますが、これは実際には、どのオーバーロードが呼び出されているかわからないために発生するバグを回避するのに役立ちます。
カテゴリを使用して、ビジターパターンを実装できます。
@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です。