Hello.
Welcome back to a new section of this video course structural patterns in this section.
We will first explore about the composite design pattern and then we will move on to the abstract design
patterns.
Finally we will dive into the bridge design pattern.
Let's move on to the first video of this section that deals with composite design pattern.
In this video we will learn about creating compositions along with binary tree compositions.
We will also try to differentiate between composite pattern and inheritance.
So we are going to start our journey through the world of structural patterns structural patterns as
the name implies help us to shape our applications with commonly used structures and relationships.
The go language by nature encourages the use of composition almost exclusively by its lack of inheritance.
Because of this we've been using the composite design pattern extensively until now.
So let's start by defining the composite design pattern the composite design pattern favors composition
commonly defined as the has a relationship over inheritance which is and is a relationship the composition
over inheritance approach has been a source of discussion among engineers since the 90s.
We will learn how to create object structures by using a has approach.
All in all go doesn't have inheritance because it doesn't need it in the composite design pattern.
You will create hierarchies of trees of objects objects have different types with their own fields and
methods inside them.
This approach is very powerful and solves many problems of inheritance and multiple inheritances.
For example a typical inheritance problem is when you have an entity that inherits from two completely
different classes which have absolutely no relationship between them.
Imagine an athlete who trains and who is a swimmer who swims the athlete class has a train method while
the swimmer class has a swim method.
The swimmer class inherits from the athlete class so it inherits its train method and declares its own
swim method.
You could also have a cyclist who is also an athlete and declares a rider method.
And now imagine an animal that eats like a dog that also barks the cyclist class as a ride method.
The Animal class has eat dog and bark methods nothing fancy.
You could also have a fish that is an animal.
And yes swims.
So how do you solve it.
A fish cannot be a swimmer that also trains fish don't train as far as I know you could make a swimmer
interface with the swim method and make the swimmer athlete and fish implement it.
This would be the best approach but you still would have to implement swim method twice so code reuse
ability would be affected.
What about a triathlete.
They are athletes who swim run and ride with multiple inheritances.
You could have a sort of solution but that would become complex and not maintainable very soon as you
have probably imagined already.
The objective of the composition is to avoid this type of hierarchy hell with the complexity of an application
could grow too much and the clarity of the code is affected.
We will solve the described problem of the athlete and the fish that swims in a very idiomatic go way
with go.
We can use two types of composition the direct composition and the embedding composition.
We will first solve this problem by using direct composition which is having everything that is needed
as fields within the struct.
Here requirements are like the ones described previously.
We'll have an athlete and a swimmer.
We will also have an animal and a fish.
The swimmer and the fish method must share the code.
The athlete must train and the animal must eat.
We must have an athlete struct with a trained method and we must have a swimmer with a swim method.
Also we must have an animal struct with an eat method and we must have a fish struct with a swim method
that is shared with the swimmer and not have inheritance or hierarchy issues.
Now let's start with creating compositions.
The composite design pattern is a pure structural pattern.
It doesn't have much to test apart from the structure itself.
We will write unit tests in this case and will simply describe the ways to create those compositions
in go.
First we start with the athlete structure and its train method.
Let's open the composite dot go file so you can see the athlete struct under the train method.
This code is pretty straightforward.
Its train method prints the word training and the new line.
We create a composite swimmer that has an athlete struct inside it.
The composite swimmer a type has a Mai athlete field of type athlete.
It also stores a funk type.
Remember that bingo functions are first class citizens and they can be used as parameters fields or
arguments just like any variable so composite swimmer a has a mile swim field that stores a closure
which takes no arguments and returns nothing.
How can I assign a function to it.
Well let's create a function that matches the function signature that is.
No arguments no return.
That's all the swimming function takes.
No arguments and returns nothing.
So it can be used as the my swim field in the composite swimmer a struct.
Now let's move to the composite underscore test dot go file and see the composite swimmer a struct.
Have a look at this piece of code because we have a function called swim function.
We can assign it to the.
My swim field.
Note that the swim type doesn't have the parenthesis that will execute its contents.
This way we take the entire function and copy it to my swim method.
But wait we haven't passed any athlete to the my athlete field and we are using it it's going to fail.
That's weird isn't it.
Not really because of the nature of zero initialization in go.
If you don't pass an athlete struct to the composite swimmer a type the compiler will create one with
its values zero initialized.
That is an athlete struct with its fields initialized to 0.
Check out Section 1.
Ready steady go to recall 0 initialization.
If this seems confusing consider the composite swimmer a struct code again.
So let's go back to the composite dots go file.
Now we have a pointer to a function stored and then my swim field.
We can assign the swim function the same way but with an extra step let me show what this extra step
is here where we have written the code for test.
Let me remove the comments first we need a variable that contains the function.
Swim.
This is because a function doesn't have an address to pass it to the composite swimmer a type.
Then to use this function within the struct we have to make a two step call.
What about our fish problem with our swim function.
It is not a problem anymore.
First we create the animal struct.
Then we create a shark object that embeds the animal object.
Wait a second.
Whereas the field name of the animal type.
Did you realize that I used the word embed previously.
This is because in go you can also embed objects within objects to make it look a lot like inheritance.
That is we won't have to explicitly call the field name to have access to its fields and method because
they'll be part of us.
So this code will be perfectly okay.
Now we have an animal type which is 0 initialized and embedded.
This is why I can call the Eat method of the animal struct without creating it or using the intermediate
field name.
Finally there is a third method to use the composite pattern.
We could create a swimmer interface with a swim method and a swimmer implement later type to embed it
in the athletes swimmer.
With this method you have more explicit control over object creation.
The swimmer field is embedded but won't be 0 initialized as it is a pointer to an interface.
The correct use of this approach will be this piece of code.
Let's save this file.
Move on to terminal and execute the command.
Go test hyphen V and here's the output for composite swimmer B.
As expected we got the output as training.
Training and swimming eating and swimming.
And the fourth one.
Training and swimming.
And we have passed the test.
Which approach is better.
Well I have a personal preference which shouldn't be considered the rule of thumb in my opinion.
The interfaces approach is the best for quite a few reasons but mainly for explicitness.
First of all you're working with interfaces which are preferred instead of struct.
Secondly you aren't leaving parts of your code to the zero initialization feature of the compiler.
It is a really powerful feature but one that must be used with care because it can lead to runtime problems
which you'll find it compile time when working with interfaces in different situations zero initialization
will save you at runtime in fact.
But I prefer to work with interfaces as much as possible.
So this is not actually one of the options.
Now let's have a look at the binary tree compositions.
So another very common approach to the composite pattern is when working with binary tree structures
in a binary tree.
You need to store instances of itself in a field.
Here's how the code looks.
This is some kind of recursive compositing and because of the nature of recursively we must use pointers
so that the compiler knows how much memory it must reserve for this struct.
Our tree struct stored a leaf value object for each instance and a new tree in its right and left fields.
Let's go to composite test.
Don't go with this structure.
We could create an object like this.
We can print the contents of its deepest branch as I've done here with this code line.
Let's move to the terminal and execute this code so you can see that the test is passed and that we
output 6 let's see composite pattern versus inheritance when using the composite design pattern and
go.
You must be very careful not to confuse it with inheritance.
For example when you embed a parent struct within a son struct like in this example you cannot consider
that the son struct is also the parent struct.
What this means is that you cannot pass an instance of the son struct to a function that is expecting
a parent struct like this piece of code.
When you try to pass a son instance to get parent field method you will get this error message.
This is a cannot use son as type parent in argument to get parent field.
This in fact makes a lot of sense.
What's the solution for this.
Well you can simply compose it.
The son struct with the parent without embedding so that you can access the parent instance later let's
add P to the son struct and also make changes to get the parent field function call.
So now you could use the P field to pass it to the get parent field method.
Let's open composite test.
Don't go.
You can see we have used the p fields to pass it to the get to parent field method.
Let's move to the terminal and here's the output for the test.
Also at this point you should be really comfortable using the composite design pattern.
It's a very idiomatic go feature and the switch from a pure object oriented language is not very painful.
The composite design pattern makes our structure predictable but also allows us to create most of the
design patterns as we will see in later sections in the next video.
We will be learning about adapter design pattern.