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