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.