The Builder Design Pattern in Ruby 🔨
Max Normand
Posted on August 1, 2023
Design patterns are fundamental to know if you’re going to build sexy and scalable applications. In this article we will be looking at the builder pattern.
Introduction
The builder pattern, is part of the “creational design patterns”. In summary it simplifies the processes of creating complex objects.
We create a builder class that should have everything we need to help ease the complexities around creating our objects.
Specification
Let’s take our robot example from a previous tutorial 🤖
A robot is a complex object, it can have many attributes, all relating to a different kind of robot build. For example, a large dumb robot in a factory, to a small child's robot. You may have some pre-set attributes. But all in all, this class is very dynamic upon generation.
Creating the complex class
class Robot
attr_accessor :colour, :ai_type, :body_type, :movement, :name, :function
def initialize(colour=nil, ai_type=nil, body_type=nil, movement=nil, name=nil, function=nil)
@colour = colour
@ai_type = ai_type
@body_type = body_type
@movement = movement
@name = name
@function = function
end
end
As you can see, initialising our class each time will be a pain, especially if we want a variation of robots. Classes like this can look unprofessional and bloat our application.
We would have to do this lots of times:
butter_robot = Robot.new(
colour = "grey",
ai_type = "too smart for own good",
body_type = "small rover",
movement = "medium",
name = "butter robot",
function = "pass the butter"
)
Creating a builder class will solve this problem 🔨
class RobotBuilder
def initialize
@robot = Robot.new
end
# We can set default attributes to save time
def set_default_parameters(colour, name, movement, body_type)
@robot.colour = colour
@robot.name = name
@robot.movement = movement
@robot.body_type = body_type
end
# We can set one attribute
def set_function(function)
@robot.function = function
end
# We can have pre-set conditions
def set_as_smart
@robot.ai_type = 'smart'
end
def set_as_dumb
@robot.ai_type = 'dumb'
end
# We can have pre-set objects ready
def set_as_terminator
@robot.ai_type = 'smart'
@robot.function = 'take over world'
@robot.movement = 'fast'
@robot.body_type = 'humanoid'
@robot.colour = 'chrome'
@robot.name = terminator_name
end
def set_as_walee
@robot.ai_type = 'loving'
@robot.function = 'to help'
@robot.movement = 'medium'
@robot.body_type = 'rover'
@robot.colour = 'rusty yellow'
@robot.name = "WALL-E"
end
def robot
@robot
end
private
# We can use all sorts of methods to help our builder logic
def terminator_name
letters = ('a'..'z').to_a.sample(3).join
numbers = rand 200..500
letters + numbers.to_s
end
end
As you can see our class does a few different things. We firstly start by initializing our builder class. Which will also in turn create our robot class.
From this initialized builder object, we can then go through various methods to set up the our robot object. As you can see, how we want to set it up is entirely configurable. We can create a nice little robot, or a terminator to destroy to world!
We can even create private methods to help with the creation of complex attributes. If you wanted, you could also pass in and initialize other objects as well. The list goes on...
Some examples of the fun we can have:
# to create a default robot
builder = RobotBuilder.new
builder.set_default_parameters(
"Red", "Robot", "Slow", "Large"
)
builder.set_as_dumb
builder.set_function("Pack boxes")
# to create a freind
builder = RobotBuilder.new
builder.set_as_walee
# to take over the world!
builder = RobotBuilder.new
builder.set_as_terminator
Conclusion
With our new builder, any further complexities for our robot can now be addressed by growing this class. The builder can be called at any point of our application, to help us create our robot army.
<3 Thanks for reading <3
Posted on August 1, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.