This is the second video of this section.
Build a design pattern where we'll be reusing an algorithm to create many implementations of an interface.
In the previous video we looked at Singleton pattern in this video.
We'll take an example of vehicle manufacturing and see the implementation talking about creation or
design patterns.
It looks pretty semantic to have a builder design pattern the builder pattern helps us construct complex
objects without directly instantiating their struct or writing the logic they require.
Imagine an object that could have dozens of fields that are more complex struct themselves.
Now imagine that you have many objects with these characteristics and you could have more.
We don't want to write the logic to create all these objects in the package that just needs to use the
objects.
Instance creation can be as simple as providing the opening and closing braces and leaving the instance
with zero values or as complex as an object that needs to make some API calls check states and create
objects or its fields.
You could also have an object that is composed of many objects something that's really idiomatic and
go as it doesn't support inheritance.
At the same time you could be using the same technique to create many types of objects.
For example you'll use almost the same technique to build a car as you would build a bus.
Except that they'll be of different sizes and number of seats so why don't we reuse the construction
process.
This is where the builder pattern comes to the rescue.
A builder design pattern tries to abstract complex creations so that object creation is separated from
the object user creates an object step by step by filling its fields and creating the embedded objects
reuse the object creation algorithm between many objects.
Let's take an example of vehicle manufacturing.
So the builder design pattern has been commonly described as the relationship between a director a few
builders and the product they build.
Continuing with our example of the car will create a vehicle builder.
The process of creating a vehicle is more or less the same for every kind of vehicle.
Choose a vehicle type assemble the structure placed the wheels and placed the seats.
If you think about it you could build a car and a motorbike or two builders.
With this description so we are reusing the description to create cars in manufacturing.
The director is represented by the manufacturing director type.
In our example.
Now let's see what are the requirements and acceptance criteria.
As far as we have described we must dispose of a builder of type Car and a motorbike and a unique director
called Manufacturing director to take builders and construct products.
So the requirements for a vehicle builder example would be as listed here.
I must have a manufacturing type that constructs everything that a vehicle needs when using a car builder.
The vehicle product with four wheels five seats and a structure defined as car must be returned.
When using a motorbike builder the vehicle product with two wheels two seats and a structure defined
as motor bike must be returned a vehicle product built by any build process builder must be open to
modifications.
Let's move on to the unit test for the vehicle builder.
With the previous acceptance criteria we will create a director variable the manufacturing director
type to use the build process represented by the product builder variables free car and motorbike.
The director is the one in charge of construction of the objects but the builders are the ones that
return the actual vehicle.
So our builder declaration will look as this.
This interface defines the steps that are necessary to build a vehicle.
Every builder must implement this interface if they are to be used by the manufacturing on every set
step.
We return the same build process so we can chain various steps together in the same statement as we'll
see later.
Finally we'll need a get vehicle method to retrieve the vehicle instance from the builder.
So we have added this method here which you can see highlighted the manufacturing director variable
is the one in charge of accepting the builders.
It has a construct method that will use the builder that is stored in manufacturing and will reproduce
the required steps the set builder method will allow us to change the builder that is being used in
the manufacturing director.
And here's the piece of code for it.
Now the product is the final object that we want to retrieve while using the manufacturing.
In this case a vehicle is composed of wheels seats and a structure as you see here.
The first builder is the car builder.
It must implement every method defined in the build process interface.
This is where we'll set the information for this particular builder.
Next the motorbike structure must be the same as the car structure as they are all builder implementations.
But keep in mind that the process of building each can be very different.
With this declaration of objects we can create the tests as I have done it here.
Now let's move to the builder underscore test not go file.
We will start with the manufacturing director and the car builder to fulfil the first two acceptance
criteria in the preceding code we are creating our manufacturing director.
That will be in charge of the creation of every vehicle during the test.
After creating the manufacturing director we create a car builder that we then passed the manufacturing
by using the set builder method.
Once the manufacturing director knows what it has to construct now we can call the constructor method
to create the vehicle product using car builder.
Finally once we have all the pieces for our car we'll call the get to vehicle method.
On car builder to retrieve a car instance.
Now we have written three small tests to check if the outcome is a car.
We check that the car has four wheels.
The structure has the description car and the number of seats is five.
We have enough data to execute the tests and make sure that they are failing so that we can consider
them reliable let us move on to the terminal and execute the command.
Go test IV and V hyphen run equal to test builder so you can see the output where the wheels of the
car must be for and they were zero structure on a car must be car and was and the third one seats on
a car must be five and they were zero perfect now we'll create tests for a motorbike builder that covers
the third and or acceptance criteria.
So let's go back to our test file.
So here we have the code for bike builder.
This code is a continuation of the car tests.
As you can see we reuse the previously created manufacturing to create the bike.
Now by passing the motorbike builder to it then we hit the construct button again to create necessary
parts and called the builder get vehicle method to retrieve the motorbike instance take a quick look
because we have changed the default number of seats for this particular motorbike to 1.
Let us go back to the builder dot go file and make changes to the bike builder type.
Let's change these values to 0.
What we want to show here is that even while having a builder you must also be able to change the default
information in the returned instance to fit some specific needs as we set the wheels manually.
We want to test this feature Let's rerun the tests so it triggers the expected behavior as we can see
here.
Now let's start implementing the manufacturing as we said earlier the manufacturing director must accept
a builder and construct a vehicle using the provided builder to recall the build process interface will
define the common steps needed to construct any vehicle and the manufacturing director must accept builders
and construct vehicles together with them.
So we have made the changes and we have added the code as you see wheels equal to four seats equal to
five and structure equal to car and the seats for bike is to our manufacturing director needs a field
to store the builder in use.
This field will be called builder the set builder method will replace the stored builder with the one
provided in the arguments.
Finally take a closer look at the construct method.
It takes the builder that has been stored and reproduces the build process method that will create a
full vehicle of some unknown type.
As you can see we have used all the settings calls in the same line.
Thanks to returning the build process interface on each of the calls this way the code is more compact.
Have you realized that the director entity and the builder pattern is a clear candidate for a singleton
pattern too.
In some scenarios it could be critical that just an instance of the director is available and that is
where you'll create a singleton pattern for the director of the builder only.
Design Patterns.
Composition is a very common technique and a very powerful one.
I've already shown you the changes that I made to this code.
Here is our first builder the car builder a builder will need to store a vehicle product object which
here we have named V.
Then we set the specific needs that a car has in our business four wheels five seats and a structure
defined as car in the get vehicle method.
We just returned the vehicle product stored within the builder.
That must be already constructed by the manufacturing director type.
Now the motorbike builder is the same as the car builder.
We defined a motorbike to have two wheels two seats and a structure called motorbike.
It's very similar to the car object but imagine that you want to differentiate between a sports motorbike
with only one seat and a Cruz motorbike with two seats.
You could simply create a new structure for sports motorbikes that implements the build process.
You can see that it's a repetitive pattern but within the scope of every method of the build process
interface you could encapsulate as much complexity as you want.
Such that the user need not know the details about the object creation with the definition of all the
objects let's run the test again.
So we've passed the test.
Well done.
Think how easy it could be to add new vehicles to the manufacturing director just to create a new class
encapsulating the data for the new vehicle.
For example here we add a bus builder struct that's all your manufacturing director would be ready to
use the new product by following the builder design pattern.
Let's save the file go to the builder design pattern helps us maintain an unpredictable number of products
by using a common construction algorithm that is used by the director.
The construction process is always abstracted from the user of the product.
At the same time having defined a construction pattern helps when a newcomer to our source code needs
to add a new product to the pipeline.
The build process interface specifies what he must comply to be part of the possible builders.
However try to avoid the builder pattern when you are not completely sure that the algorithm is going
to be more or less stable because any small change in this interface will affect all your builders and
it could be awkward if you add a new method that some of your builders need and other builders do not
in this video.
We explored about the builder design pattern in the next video.
We will be learning about factory method.