Template Method Design Pattern

Back in September, I wrote about the strategy design pattern and suggested that it could be useful in iPhone and iPad programming to provide alternate implementations of a piece of functionality. When thinking about strategy, think “plugin”. Strategy implies a relationship between classes where a class has a strategy object to do specific work. In object-oriented terminology, this is aggregation, where an object “has-a” reference to a worker.

There is another style of objects working together called composition. In this case, an object “is-a” derivative of another. A classic implementation of composition is the template method design pattern and it probably won’t surprise you to learn that there are applications of this in iPhone and iPad programming too.

NSFetchedResultsController

When working with Core Data on iOS, there is a very useful class called NSFetchedResultsController that can be used to monitor changes to a Core Data data model and update the user-interface, in particular a table-view, automatically.

I won’t go into the details, because that’s not the point of the post, but if you want to know more, fetched results controllers are a new topic in the new revision of Learning Tree’s Building iPhone® and iPad® Applications: Extended Features course. (Work on which has been distracting me from blog posts over the past few weeks but is now in the final stages of testing and should be available to run from the end of November).

One of the advantages of the fetched results controller is that it standardizes the table view data source methods. For example:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return [[self.fetchedResultsController sections] count];
}

Nothing specific in there. No references to the type of object the table view is displaying and so on. So the temptation when creating another table view controller is to reach for copy and paste. The alarm bells start ringing — there must be a better way …

… and there is. You can make a superclass and push these methods up into it. Xcode even has refactoring tools to help you.

Template Method

It all goes swimmingly well until you get to the tableView:cellForRowAtIndexPath method. This is where the specifics of your table view controller, i.e. the specific data it displays, start to bite. You could simply choose not to push that method up into the superclass.

MyTableViewController.m

- (UITableViewCell *)tableView:(UITabelView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
        dequeueReusableCellWithIdentifier:@"Cell"
        forIndexPath:indexPath
    ];

    // Configure the cell
    SomeData *someData = [self.fetchedResultsController
        objectAtIndexPath:indexPath
    ];
    cell.textLabel.text = someData.someProperty;
    cell.detailTextLabel.text = someData.someOtherProperty;

    return cell;
}

But here’s where the template method comes in. The idea of the template method pattern is to take a standard algorithm and provide a customization option through subclassing. The standard algorithm in this case is:

  1. Dequeue a cell
  2. Configure a cell
  3. Return the cell

If we put that algorithm into the superclass we created, we can create a template method that we can override in the subclass and it will be called in the correct place:

BaseTableViewController.m

- (UITableViewCell *)tableView:(UITabelView *)tableView
    cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
        dequeueReusableCellWithIdentifier:@"Cell"
        forIndexPath:indexPath
    ];

    // The template method
    [self configureCell:cell];

    return cell;
}

- (void)configureCell:(UITableViewCell *)cell
{
    // Do nothing, this method is overridden by the subclass. We need it here
    // or this class won't compile. In a language like Java, we would
    // make this an abstract method. In C++ terms, pure-virtual.
    abort(); // Fail if this method is not subclassed
}

So in our table view controller that is a subclass of the BaseTableViewController:

MyTableViewController.n

- (void)configureCell:(UITableViewCell *)cell
{
    SomeData *someData = [self.fetchedResultsController
        objectAtIndexPath:indexPath
    ];
    cell.textLabel.text = someData.someProperty;
    cell.detailTextLabel.text = someData.someOtherProperty;
}

The MyTableViewController class inherits the standard methods that we pushed up but provides a specific implementation of the configureCell: method

Now you might be thinking that’s an algorithm that is too simple to get wrong and probably doesn’t warrant the use of a template method. You may be right but it’s the principle of the template method that I’m trying to illustrate: an algorithm defined in a base class where the customization point in a subclass is achieved by providing an implementation of the template method.

Once you understand the pattern, hopefully you will recognize when to apply it in more complex algorithms where one step needs to be customized but the rest of the algorithm is constant.

Richard Senior

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.