だから私はObjective-Cのテンプレートメソッドについて読んでいて、それらの何が特別なのかを理解しようとしています. 私の理解では、基本クラスのメソッドはオーバーライドでき、スーパーを呼び出すことができますか? では、テンプレート メソッドは基本クラスのメソッドをオーバーライドする以上のものなのでしょうか?
私が間違っている場合は、テンプレート メソッド パターンとは何かを説明してください。また、例を挙げていただけますか?
だから私はObjective-Cのテンプレートメソッドについて読んでいて、それらの何が特別なのかを理解しようとしています. 私の理解では、基本クラスのメソッドはオーバーライドでき、スーパーを呼び出すことができますか? では、テンプレート メソッドは基本クラスのメソッドをオーバーライドする以上のものなのでしょうか?
私が間違っている場合は、テンプレート メソッド パターンとは何かを説明してください。また、例を挙げていただけますか?
はい、テンプレート パターンは、基本クラスのメソッドをオーバーライドするだけではありません。
テンプレートパターンは、アルゴリズムの概要が具体的に定義されている場合に使用できますが、アルゴリズムの手順は抽象化されています。つまり、さまざまな方法で手順を実装できるということです。ただし、アルゴリズムの概要は変更されない予定です。
その場で作成したばかりの例:
class Life {
public method goThroughTheDay(){
goToWork();
eatLunch();
comeBackHome();
programABitMore();
}
abstract method goToWork();
abstract method eatLunch();
abstract method comeBackHome();
abstract method programABitMore();
}
class GoodLife extends Life {
//override all the abstract methods here
}
//The client application
Life life = new GoodLife();
life.goThroughTheDay();
基本的に、Life クラスでは、1 日の流れ方が具体的に定義されています。ただし、プロセスの詳細はサブクラス (つまり、GoodLife) によって処理されます。GoodLife クラスは、可能な ToughLife クラスとは非常に異なる手順を実装します。
このパターンにはいくつかのバリエーションがあります。たとえば、いくつかのステップを具体的に定義することもできます。この例では、eatLunch() は Life クラスで具体的に定義できます。つまり、サブクラスがこの動作を変更することは期待されていません。
さまざまな方法で実装できる比較的複雑なアルゴリズムがある場合、パターンは非常に理にかなっています。
======================================
私の答えでは、どういうわけかObjective-Cの部分を見逃していました。Objective-C では次のようになります。
@interface Life : NSObject
- (void) goThroughTheDay;
- (void) goToWork; // Abstract
- (void) eatLunch; // Abstract
- (void) comeBackHome; // Abstract
- (void) programABitMore; // Abstract
@end
@implementation Life
- (void) goThroughTheDay {
[self goToWork];
[self eatLunch];
[self comeBackHome];
[self programABitMore];
}
- (void) goToWork { [self doesNotRecognizeSelector:_cmd]; }
- (void) eatLunch { [self doesNotRecognizeSelector:_cmd]; }
- (void) comeBackHome { [self doesNotRecognizeSelector:_cmd]; }
- (void) programABitMore { [self doesNotRecognizeSelector:_cmd]; }
@end
@interface GoodLife : Life
@end
@implementation GoodLife
- (void) goToWork { NSLog(@"Good Work"); }
- (void) eatLunch { NSLog(@"Good Lunch"); }
- (void) comeBackHome { NSLog(@"Good Comeback"); }
- (void) programABitMore { NSLog(@"Good Programming"); }
@end
Objective-C には抽象クラスのサポートが組み込まれていないため、doesNotRecognizeSelector:
メソッドを使用して回避しました。抽象クラスと Objective-C の詳細については、こちらを参照してください。
もっとObjective-C固有の答えを出すべきだと思いました。Cocoa で使用されているテンプレート メソッドについては、apples Cocoa Design Patterns ページで読むことができます。この例は、drawRect:
テンプレート メソッドです。他のテンプレート メソッドと同様に、テンプレート メソッドを自分で直接呼び出すことはありません。によって呼び出されsetNeedsDisplay
ます。これのポイントは、フレームワークが描画を最適化できるようにすることです。自分で直接呼び出した場合、drawRect:
不要な再描画を何度も行うことになる可能性があります。
実際、サブクラスでオーバーライドしたいすべてのメソッドをテンプレート メソッドにするようにしてください。これにより、オーバーライド時に基本クラスの実装を呼び出す必要があるかどうかを知る問題が軽減され、デバッグが容易になります。サブクラスのすべてのオーバーライドされたメソッドではなく、基本クラスにブレークポイントを配置するだけです。
私の理解では、基本クラスのメソッドはオーバーライドでき、スーパーを呼び出すことができますか? では、テンプレート メソッドは基本クラスのメソッドをオーバーライドする以上のものなのでしょうか?
はい、これは基本クラスのメソッドをオーバーライドするだけではありません。テンプレート メソッドは、一部のステップがサブクラスに依存するアルゴリズムを実装する方法です。たとえば、3 つの主要なステップ、f1、f2、および f3 を持つ Base のメソッドを考えてみましょう。各ステップには、いくつかのステートメントが含まれています。ここで、f1 と f3 はすべてのサブクラスで同じですが、f2 はサブクラスに依存しています。では、ここで何をすべきか?f1 と f3 のサブクラス コピー ステートメントでメソッド全体をオーバーライドできますが、それは無駄です。したがって、サブクラスで f2 のみを提供します。このように、基本クラスでアルゴリズムを定義します (f1 を実行し、次に f2 を実行し、次に f3 を実行します) が、サブクラス (f2) のオーバーライド フックを提供します。基本クラスのテンプレート メソッドは final であるため、サブクラスはアルゴリズムを変更できないことに注意してください。たとえば、f1、f2、および f3 の順序を変更することはできず、サブクラスはステップ f1、f3 を省略できません。
要するに、テンプレート メソッド パターンは単なるオーバーライドではなく、特定の状況を処理するために継承を使用することです。これは Obj-C 固有のものではなく、Obj-C 固有のものを提供することはできません。このパターンの全体像を把握するには、次のことをお勧めします。
また、ウェブ上にはたくさんのチュートリアル/記事があります。基本的な考え方は Obj-C に依存しません。