The Template Method pattern is simply a fancy way of saying that if you want to vary
an algorithm, one way to do so is to separate the invariant part in a base class and
encapsulate the variable parts in methods that are defined by a number of subclasses.
The base class can simply leave the methods completely undefined (call Hooks method )
—in that case, the subclasses must supply the methods. Alternatively, the base class can provide a default implementation for the methods that the subclasses can override if they want.
For instance, let's say you have a PostsController in your Rails application that has an index action to display a list of posts. The index action follows a certain sequence of steps, such as fetching all posts from the database and rendering them in the view. Here's how you could implement the index action using the Template Method pattern:
class PostsController < ApplicationController
def index
@posts = fetch_posts
render_posts
end
private
def fetch_posts
# This method is the hook that subclasses can override to fetch posts
Post.all
end
def render_posts
# Hook method that need to overwrite
raise "Undefined method `render_posts` in subclasses"
end
end
In this implementation, the index action defines the skeleton of the algorithm for displaying a list of posts. It first calls the fetch_posts method, which is a hook that subclasses can override to customize how posts are fetched (e.g., by adding conditions or scopes). Then, it calls the render_posts method, which is another hook that subclasses can override to customize how posts are rendered (e.g., by using a different view template or format).
Now, if you want to create a specialized version of the PostsController that only displays posts that have been published, you can subclass PostsController and override the fetch_posts method:
class PublishedPostsController < PostsController
private
def fetch_posts
Post.published
end
end
This implementation of PublishedPostsController inherits the index action from PostsController but customizes the behavior of the fetch_posts hook to only fetch posts that have been published. When you visit the index action of PublishedPostsController, it will only show published posts.