因此,我一直在阅读有关 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 类中具体定义的。但是,该过程的细节由子类(即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 设计模式页面上阅读 Cocoa 中使用的模板方法。一个例子是drawRect:
模板方法。像其他模板方法一样,您永远不会自己直接调用模板方法。它由 调用setNeedsDisplay
。这样做的目的是让框架优化绘图。如果您drawRect:
直接调用自己,您最终可能会多次进行不必要的重绘。
In fact you should probably try to make every method you want to override in a subclass a template method. This reduce the problem of knowing whether you should call the base class implementation when you override and makes debugging easier. You can just put a breakpoint in the base class, instead of every overridden methods in the subclasses.
据我了解,基类中的任何方法都可以被覆盖并且可以调用超级?那么模板方法不仅仅是覆盖基类中的方法吗?
是的,这不仅仅是覆盖基类方法。模板方法是一种实现算法的方法,其中某些步骤依赖于子类。例如,考虑 Base 中的一个方法,它具有三个主要步骤,f1、f2 和 f3。每个步骤都包含许多语句。这里 f1 和 f3 在所有子类中都相同,但 f2 是子类相关的。那么在这里做什么呢?您可以在 f1 和 f3 的子类复制语句中覆盖整个方法,但这是一种浪费。所以你在子类中只提供 f2 。通过这种方式,您可以在基类中定义算法(执行 f1,然后执行 f2,然后执行 f3),但为子类 (f2) 提供覆盖挂钩。注意,基类中的模板方法是final的,所以子类不能改变算法,例如不能改变f1、f2、f3的顺序,任何子类都不能省略f1、f3步骤。
简而言之,模板方法模式不仅仅是覆盖,它是使用继承来处理一些特定的情况。这不是 Obj-C 特定的,我无法为您提供任何特定于 Obj-C 的内容。要全面了解此模式,我建议以下内容:
网上也有大量的教程/文章。基本思想不依赖于 Obj-C。