Post

Creational Design Patterns: Builder Method

Purpose

Imagine you want to build different types of vehicles: a car, a bike, or even a truck. Each vehicle has various features: the number of wheels, the type of engine, color, and more. If you try to create these vehicles using a single constructor with many parameters, it can quickly become confusing and hard to manage.

This is where the Builder Pattern comes in! It helps you construct these complex objects step by step, making your code cleaner and easier to read.

Explanation

  • Separation of Concerns: The Builder Pattern separates the construction of an object from how it’s represented. This means that you can use the same process to create different types of vehicles without mixing up their configurations.

  • Simplified Creation Process: Instead of having to remember a long list of parameters for creating a vehicle, you can set each feature one at a time. This way, it’s clear what you’re configuring, which makes the code more understandable.

  • Flexibility: You can easily change how a vehicle is built without changing the way it’s used. For instance, if you decide to add more features to a bike, you can do that in the BikeBuilder without affecting how cars are built.

  • Immutability: If you want to create vehicles that can’t be changed once they’re built, the Builder Pattern allows you to construct them in a way that supports immutability.

Ruby Example: Vehicle Factory

Let’s look at how we can implement the Builder Pattern using a Vehicle class in Ruby:

Step 1: Define the Product Class

This class represents our final product—the vehicle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Vehicle
  attr_accessor :type, :wheels, :engine, :color

  def initialize(type, wheels, engine, color)
    @type = type
    @wheels = wheels
    @engine = engine
    @color = color
  end

  def to_s
    "Vehicle Type: #{@type}, Wheels: #{@wheels}, Engine: #{@engine}, Color: #{@color}"
  end
end

Here, Vehicle has attributes like type, wheels, engine, and color. We can print the vehicle’s details using the to_s method.

Step 2: The Builder Interface

Next, we create a builder interface, which will outline how we can build a vehicle.

1
2
3
4
5
6
7
class VehicleBuilder
  def set_type(type); end
  def set_wheels(wheels); end
  def set_engine(engine); end
  def set_color(color); end
  def build; end
end

This interface defines the methods we’ll need to build a vehicle, but doesn’t provide any specific implementation.

Step 3: Concrete Builders

Now, we implement specific builders for different types of vehicles, like cars and bikes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class CarBuilder < VehicleBuilder
  def initialize
    @vehicle = Vehicle.new('Car', 4, 'Petrol', 'Red')
  end

  def set_type(type)
    @vehicle.type = type
  end

  def set_wheels(wheels)
    @vehicle.wheels = wheels
  end

  def set_engine(engine)
    @vehicle.engine = engine
  end

  def set_color(color)
    @vehicle.color = color
  end

  def build
    @vehicle
  end
end

class BikeBuilder < VehicleBuilder
  def initialize
    @vehicle = Vehicle.new('Bike', 2, 'Petrol', 'Blue')
  end

  def set_type(type)
    @vehicle.type = type
  end

  def set_wheels(wheels)
    @vehicle.wheels = wheels
  end

  def set_engine(engine)
    @vehicle.engine = engine
  end

  def set_color(color)
    @vehicle.color = color
  end

  def build
    @vehicle
  end
end

Each builder initializes a Vehicle object with default values and provides methods to set the various attributes.

Step 4: The Director

We then create a VehicleDirector, which will guide the building process.

1
2
3
4
5
6
7
8
9
10
11
12
13
class VehicleDirector
  def initialize(builder)
    @builder = builder
  end

  def construct_vehicle
    @builder.set_type('Custom Vehicle')
    @builder.set_wheels(4)
    @builder.set_engine('Electric')
    @builder.set_color('Green')
    @builder.build
  end
end

The director takes a builder and uses it to create a vehicle with specified features.

Step 5: Putting It All Together

Finally, let’s see how we can use these builders to create vehicles.

1
2
3
4
5
6
7
8
9
10
11
# Creating a Car
car_builder = CarBuilder.new
director = VehicleDirector.new(car_builder)
car = director.construct_vehicle
puts car.to_s

# Creating a Bike
bike_builder = BikeBuilder.new
director = VehicleDirector.new(bike_builder)
bike = director.construct_vehicle
puts bike.to_s

Output

When you run the above code, it produces:

1
2
Vehicle Type: Custom Vehicle, Wheels: 4, Engine: Electric, Color: Green
Vehicle Type: Bike, Wheels: 2, Engine: Petrol, Color: Blue

Conclusion

The Builder Pattern is like a friendly guide that helps you construct different vehicles in an organized way. Instead of throwing a bunch of parameters at a constructor and hoping it all works, you build your vehicle step by step, clearly indicating what each feature is. This makes your code cleaner, easier to understand, and much more flexible.

Whether you’re building cars, bikes, or any other complex objects, the Builder Pattern is a great way to streamline the process!

Enjoy :)

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.