factoryFactory Method
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.
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