menu
Creationalarrow_forward_ios
Factory Method
factoryFactory Method

Description

Factory Method is a creational design pattern that creates a common interface for creating objects in a base class and then prepare specific implementations in subclasses. It is a creational equivalent of Template Method.

Problem

We can use the same example from previous article about Abstract Factory. We want to create code to operate a virtual bar. We will serve various types of alcohol in our bar. The instructions for preparing each drink will be the same and will consist of the following steps:
  • prepare glass
  • add alcohol
  • add additions
Below is a base class that prepare common behavior that allow us to create a drink but do not implement behavior for specific methods.

class Drink
  attr_reader :glass, :alcohol, :additions

  def initialize
    @glass = prepare_glass
    @alcohol = add_alcohol
    @additions = add_additions
  end

  def prepare_glass
    raise NoMethodError
  end

  def add_alcohol
    raise NoMethodError
  end

  def add_additions
    raise NoMethodError
  end
end
We have already written the main code that will allow us to create the drink. Now we need to create implementations for a specific drink.

class WhiskyDrink < Drink
  def prepare_glass
    Glass.new(size: 200)
  end

  def add_alcohol
    Whisky.new
  end

  def add_additions
    [Ice.new, Ice.new, Lime.new]
  end
end
The code looks almost identical to the one we used for the Abstract Method. The only change is that the class inherits from the Drink class.
Let’s also prepare similar code that will allow us to create a shot of Vodka.

class VodkaDrink < Drink
  def prepare_glass
    Glass.new(size: 40)
  end

  def add_alcohol
    Vodka.new
  end

  def add_additions
    nil
  end
end
We have almost everything ready. Let’s add the classes that are in individual classes.

# Real implementations of those classes are not important for this example.
class Vodka; end
class Whisky; end
class Ice; end
class Lime; end

class Glass
  attr_reader :size
  def initialize(size: nil)
    @size = size
  end
end
Now that everything is ready, we can easily create our drinks. Unlike Abstract Factory we do not need to use a base class because all behavior is inherited by its subclasses.

vodka = VodkaDrink.new
whisky = WhiskyDrink.new

vodka.glass.size # => 40