Design Patterns in Ruby: Template Method pattern
Tags: ruby, designpatterns, templatemethod
Published: 2018-08-21 10:56:39

---
title: Design Patterns in Ruby: Template Method pattern
published: true
description: Learn how to apply the Template Method pattern in your ruby code
tags: [ruby, design patterns, template method]
---

> By definition, the pattern defines a skeleton of an algorithm, but leave certain parts of this algorithm to be implemented by subclasses. Those subclasses can override the main behavior, without a need to change the main structure of the base algorithm.

In other words, the base class defines a skeleton and subclasses must fill this skeleton with your own implementation.

## Deal with different membership plans

Let's say that you need to add a membership feature to your application, and the membership has two different plans, the basic and the premium. Each of these plans has their own title, description and a bunch of benefits.

At first try, you can simply add an if statement to check which `type` plan will be created, and it seems a good idea.

```ruby
class Plan
  attr_reader :title, :description, :benefits

  def initialize(kind)
    if kind == :basic
      @title = "I'm the basic plan"
      @description = "My description of basic plan"
      @benefits = ['It is free', 'Access to one account', 'Basic features']
    else
      @title = "I'm the other plan"
      @description = "My description of other plan"
      @benefits = ['No benefits']
    end
  end

  def output
    output = <<-STRING
      Title: #{title}
      Description: #{description}
      Plan benefits: #{benefits.join(', ')}.
    STRING

    puts(output)
  end
end

####

basic = Plan.new(:basic)
basic.output

"""
Title: I'm the basic plan
Description: My description of basic plan
Plan benefits: It is free, Access to one account, Basic features.
"""

other_plan = Plan.new(:other)
other_plan.output

"""
Title: I'm the other plan
Description: My description of other plan
Plan benefits: No benefits.
"""
```

But, what will happen if we need to add a check for a new plan called `premium`? If we keep in this approach, the code will look like this:

```ruby
class Plan
  attr_reader :title, :description, :benefits

  def initialize(kind)
    if kind != :basic
      @title = "I'm the basic plan"
      @description = "My description of basic plan"
      @benefits = ['It is free', 'Access to one account', 'Basic features']
    elsif kind == :premium
      @title = "I'm the premium plan"
      @description = "My description of premium plan"
      @benefits = ['It is paid', 'Access to ten accounts', 'Premium features', 'Access to support']
    else
      @title = "I'm the other plan"
      @description = "My description of other plan"
      @benefits = ['No benefits']
    end
  end

  # ...
end
```

And what if we need to add a new plan called `master premium`? Yeah, this approach will not scale well and will deny the code to be flexible and with support many plans.

## Using Template Method Pattern to allow multiple plans

As I said before, the main definition of `Template Method` pattern is to define a skeleton and let the subclasses to fill this skeleton with their own implementation.

So let's define the base class:

```ruby
class Base
  def title
    raise 'Must implement'
  end

  def description
    raise 'Must implement'
  end

  def benefits
    raise 'Must implement'
  end

  def output
    output = <<-STRING
      Title: #{title}
      Description: #{description}
      Plan benefits: #{benefits}.
    STRING

    puts(output)
  end
end
```

It's pretty basic, the `Base` class just define 3 methods `title`, `description` and `benefits`. The `output` method, contains the skeleton algorithm with the behaviors that subclasses will implement.

The importance of `Base` class is to define an interface that all subclasses must follow and implement.

Now let's create the subclasses:

```ruby
class BasicPlan < Base
  def title
    "I'm the basic plan"
  end

  def description
    "My description of basic plan"
  end

  def benefits
    ['It is free', 'Access to one account', 'Basic features'].join(', ')
  end
end

###

class PremiumPlan < Base
  def title
    "I'm the premium plan"
  end

  def description
    "My description of premium plan"
  end

  def benefits
    [
      'It will cost USD 10.00',
      'Access to ten accounts',
      'Premium features',
      'You will receive a gift on your birthday'
    ].join(', ')
  end
end
```

Each subclass implement your own behavior for each method without worrying about `output` method, your only
a concern is to implement the hook methods, that will be used inside `Base#output`.

And what happens if we need to add a new membership plan? Well, it very simple, we just need to create the new class and implement `Base` class methods.

```ruby
class AwesomePlan < Base
  def title
    "I'm the awesome plan"
  end

  def description
    "My description of awesome plan"
  end

  def benefits
    [
      'It will cost USD 1,000.00',
      'Access to a hundread accounts',
      'Awesome features',
      'You will receive a gift on your birthday',
    ].join(', ')
  end
end

###

"""
Title: I'm the awesome plan
Description: My description of awesome plan
Plan benefits: It will cost USD 1,000.00, Access to a hundread accounts, Awesome features, You will receive a gift on your birthday.
"""
```

Well, this is it, this is how to use the Template Method pattern with Ruby.

### References

- [Marcos Brizeno](https://brizeno.wordpress.com/category/padroes-de-projeto/template-method/)
- [Dockyard](https://dockyard.com/blog/ruby/2013/07/10/design-patterns-template-pattern)