关于Objective-C:Objective-C – 模板方法模式?

Objective-C - Template methods pattern?

所以我一直在阅读关于Objective-C的模板方法,我试图理解它们有什么特别之处。根据我的理解,基类中的任何方法都可以被重载,并且可以调用super?那么,模板方法是否比重写基类中的方法更重要呢?

如果我错了,你能解释一下什么是模板方法模式吗?你能举个例子吗?


是的,模板模式不仅仅是重写基类中的方法。

当一个算法的轮廓被具体定义时,可以使用模板模式,但是该算法的步骤是抽象的。这意味着这些步骤可以以不同的方式实现。但是,该算法的总体轮廓预计不会改变。

我刚刚创建的一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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();

基本上,一天的运行方式是在生命类中具体定义的。但是,该流程的细节由子类(即goodlife)负责。GoodLife类将执行与可能的Toughlife类非常不同的步骤。

这种模式有一些变化;例如,一些步骤也可以具体定义。在这个例子中,eat午餐()可以在life类中具体定义;这意味着子类不应该改变这种行为。

如果您有一个相对复杂的算法,可以用不同的方式实现,那么模式就非常有意义。

======================

我不知怎么地错过了答案中客观C的部分。以下是目标C中的情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@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:方法来解决它。这里可以找到关于抽象类和目标C的更多详细信息。


我想我应该给出一个更客观具体的答案。您可以在苹果可可设计模式页面上阅读可可中使用的模板方法。这方面的一个例子是drawRect:模板方法。和其他模板方法一样,您永远不会直接调用模板方法。它被setNeedsDisplay调用。重点是允许框架优化绘图。如果你自己直接打电话给drawRect:,你可能会结束多次不必要的重画。

实际上,您可能应该尝试使子类中要重写的每个方法都成为模板方法。这减少了在重写时知道是否应该调用基类实现的问题,并使调试更加容易。您可以在基类中放置一个断点,而不是在子类中放置所有重写的方法。


From my understanding any method in a Base class can be over-ridden and super can be called? So is a template method anything more than overriding a method in the base class?

是的,这不仅仅是重写基类方法。模板方法是一种实现算法的方法,其中有些步骤与子类相关。例如,考虑一个基本方法,它有三个主要步骤:f1、f2和f3。每个步骤包含许多语句。这里,f1和f3在所有的子类中都是相同的,但是f2是子类相关的。那么在这里做什么呢?您可以在复制f1和f3语句的子类中重写整个方法,但这是浪费。所以在子类中只提供F2。这就是在基类中定义算法(执行f1,然后执行f2,然后执行f3),但是为子类(f2)提供覆盖钩子。请注意,基类中的模板方法是最终的,因此子类不能更改算法,例如它不能更改f1、f2和f3的顺序,子类也不能省略步骤f1、f3。

简而言之,模板方法模式不仅仅是重写,它还使用继承来处理某些特定的情况。这不是obj-c特定的,我不能向您提供obj-c特定的任何内容。为了全面了解此模式,我建议您执行以下操作:

  • GOF设计图案书
  • 头部优先设计模式
  • 维基百科关于模板方法的文章
  • 网络上也有大量的教程/文章。基本思想不依赖于obj-c。