Objective-C - Template methods pattern?

2019-01-23 19:40发布

问题:

So I've been reading about template methods on Objective-C and I am trying to understand what's so special about them. 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?

If I'm wrong, can you please explain what a template-method-pattern is, and can you provide an example?

回答1:

Yes, the template pattern is a bit more than just overriding a method in the base class.

Template pattern can be used when an outline of an algorithm is concretely defined, however the steps of the algorithm are left abstract. That means that the steps can be implemented in different ways. But, the general outline of the algorithm is not expected to change.

An example that I have just created on the fly:

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();

Basically, the way a day is expected to run down is concretely defined in the Life class. However, the details of the process are taken care by the subclass (ie. GoodLife). GoodLife class will implement steps very differently than a possible ToughLife class.

There are some variations to this pattern; for example some of the steps can also be concretely defined. In the example, the eatLunch() can be concretely defined in the Life class; meaning that the subclasses are not expected to change this behaviour.

The pattern makes a lot of sense if you have a relatively complex algorithm that could be implemented in different ways.

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

I somehow missed the part with Objective-C in my answer. Here is how it would look in 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 doesn't have built-in support for abstract classes, so I worked around it using the doesNotRecognizeSelector: method. A lot more details about the abstract classes & Objective-C can be found here.



回答2:

I thought I should give a more Objective-C specific answer. You can read about the template method as used in Cocoa on apples Cocoa Design Patterns pages. An example of this is the drawRect: template method. Like other template methods, you never call a template methods directly yourself. It is called by setNeedsDisplay. The point of this is to allow the framework to optimize the drawing. If you called drawRect: directly yourself you might end up doing redraws unnecessary many times.

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.



回答3:

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?

Yes, this is much more that just overriding a base class method. Template methods is a way to implement an algorithm where some steps are subclass dependent. For example consider a method in Base which has three major steps, f1, f2 and f3. Each steps contains a number of statements. Here f1 and f3 are same in all subclass, but f2 is subclass dependent. So what to do here? You can override the whole method in subclass copying statements of f1 and f3, but that is a waste. So you provide only f2 in subclass. And in this is way you define the algorithm (execute f1, then execute f2, then execute f3) in base class but provide overriding hooks for subclasses (f2). Note that, template method in base class is final, so subclass can't change the algorithm, e.g. it can't change the order of f1, f2 and f3, neither subclass can omit the steps f1, f3.

In short, Template Methods pattern is not just overriding, it is the use of inheritance to handle some specific situations. This is not Obj-C specific, and I can't provide you anything specific to Obj-C. To get an overall idea about this pattern, I recommend the followings:

  1. Design Patterns book by GoF
  2. Head First Design Patterns
  3. Wikipedia article on Template Method

And there are also tons of tutorials/articles on web. The basic idea is not Obj-C dependent.