WEBVTT 00:00.330 --> 00:01.130 Hello. 00:01.200 --> 00:06.930 Welcome back to a new section of this video course structural patterns in this section. 00:06.930 --> 00:12.270 We will first explore about the composite design pattern and then we will move on to the abstract design 00:12.270 --> 00:13.290 patterns. 00:13.290 --> 00:17.070 Finally we will dive into the bridge design pattern. 00:17.170 --> 00:22.500 Let's move on to the first video of this section that deals with composite design pattern. 00:22.710 --> 00:28.170 In this video we will learn about creating compositions along with binary tree compositions. 00:28.170 --> 00:32.720 We will also try to differentiate between composite pattern and inheritance. 00:33.090 --> 00:38.700 So we are going to start our journey through the world of structural patterns structural patterns as 00:38.700 --> 00:44.710 the name implies help us to shape our applications with commonly used structures and relationships. 00:44.960 --> 00:52.260 The go language by nature encourages the use of composition almost exclusively by its lack of inheritance. 00:52.260 --> 00:56.700 Because of this we've been using the composite design pattern extensively until now. 00:56.730 --> 01:04.190 So let's start by defining the composite design pattern the composite design pattern favors composition 01:04.400 --> 01:11.990 commonly defined as the has a relationship over inheritance which is and is a relationship the composition 01:11.990 --> 01:16.620 over inheritance approach has been a source of discussion among engineers since the 90s. 01:16.790 --> 01:21.410 We will learn how to create object structures by using a has approach. 01:21.410 --> 01:27.560 All in all go doesn't have inheritance because it doesn't need it in the composite design pattern. 01:27.560 --> 01:33.110 You will create hierarchies of trees of objects objects have different types with their own fields and 01:33.110 --> 01:34.640 methods inside them. 01:34.640 --> 01:40.680 This approach is very powerful and solves many problems of inheritance and multiple inheritances. 01:40.730 --> 01:46.400 For example a typical inheritance problem is when you have an entity that inherits from two completely 01:46.400 --> 01:50.660 different classes which have absolutely no relationship between them. 01:50.690 --> 01:58.100 Imagine an athlete who trains and who is a swimmer who swims the athlete class has a train method while 01:58.100 --> 02:01.130 the swimmer class has a swim method. 02:01.130 --> 02:07.520 The swimmer class inherits from the athlete class so it inherits its train method and declares its own 02:07.520 --> 02:08.810 swim method. 02:08.810 --> 02:13.900 You could also have a cyclist who is also an athlete and declares a rider method. 02:13.900 --> 02:21.450 And now imagine an animal that eats like a dog that also barks the cyclist class as a ride method. 02:21.560 --> 02:26.310 The Animal class has eat dog and bark methods nothing fancy. 02:26.360 --> 02:28.150 You could also have a fish that is an animal. 02:28.160 --> 02:29.540 And yes swims. 02:29.600 --> 02:31.450 So how do you solve it. 02:31.460 --> 02:37.730 A fish cannot be a swimmer that also trains fish don't train as far as I know you could make a swimmer 02:37.760 --> 02:42.950 interface with the swim method and make the swimmer athlete and fish implement it. 02:42.980 --> 02:48.470 This would be the best approach but you still would have to implement swim method twice so code reuse 02:48.470 --> 02:50.220 ability would be affected. 02:50.240 --> 02:51.870 What about a triathlete. 02:51.890 --> 02:56.630 They are athletes who swim run and ride with multiple inheritances. 02:56.630 --> 03:03.230 You could have a sort of solution but that would become complex and not maintainable very soon as you 03:03.230 --> 03:05.150 have probably imagined already. 03:05.150 --> 03:10.910 The objective of the composition is to avoid this type of hierarchy hell with the complexity of an application 03:10.910 --> 03:15.150 could grow too much and the clarity of the code is affected. 03:15.230 --> 03:21.440 We will solve the described problem of the athlete and the fish that swims in a very idiomatic go way 03:22.070 --> 03:22.790 with go. 03:22.790 --> 03:28.760 We can use two types of composition the direct composition and the embedding composition. 03:28.760 --> 03:34.040 We will first solve this problem by using direct composition which is having everything that is needed 03:34.190 --> 03:36.180 as fields within the struct. 03:36.380 --> 03:39.830 Here requirements are like the ones described previously. 03:39.890 --> 03:42.230 We'll have an athlete and a swimmer. 03:42.230 --> 03:44.510 We will also have an animal and a fish. 03:44.510 --> 03:47.870 The swimmer and the fish method must share the code. 03:47.870 --> 03:52.460 The athlete must train and the animal must eat. 03:52.460 --> 03:58.490 We must have an athlete struct with a trained method and we must have a swimmer with a swim method. 03:58.490 --> 04:04.790 Also we must have an animal struct with an eat method and we must have a fish struct with a swim method 04:04.970 --> 04:09.950 that is shared with the swimmer and not have inheritance or hierarchy issues. 04:09.950 --> 04:12.770 Now let's start with creating compositions. 04:12.950 --> 04:17.190 The composite design pattern is a pure structural pattern. 04:17.210 --> 04:20.720 It doesn't have much to test apart from the structure itself. 04:20.720 --> 04:25.880 We will write unit tests in this case and will simply describe the ways to create those compositions 04:26.000 --> 04:27.310 in go. 04:27.470 --> 04:32.040 First we start with the athlete structure and its train method. 04:32.120 --> 04:39.410 Let's open the composite dot go file so you can see the athlete struct under the train method. 04:39.410 --> 04:41.480 This code is pretty straightforward. 04:41.510 --> 04:45.590 Its train method prints the word training and the new line. 04:45.710 --> 04:49.930 We create a composite swimmer that has an athlete struct inside it. 04:50.150 --> 04:55.610 The composite swimmer a type has a Mai athlete field of type athlete. 04:55.610 --> 04:57.800 It also stores a funk type. 04:57.800 --> 05:03.800 Remember that bingo functions are first class citizens and they can be used as parameters fields or 05:03.800 --> 05:11.600 arguments just like any variable so composite swimmer a has a mile swim field that stores a closure 05:12.020 --> 05:15.180 which takes no arguments and returns nothing. 05:15.200 --> 05:17.450 How can I assign a function to it. 05:18.080 --> 05:22.390 Well let's create a function that matches the function signature that is. 05:22.400 --> 05:24.740 No arguments no return. 05:24.740 --> 05:26.630 That's all the swimming function takes. 05:26.630 --> 05:28.460 No arguments and returns nothing. 05:28.610 --> 05:34.160 So it can be used as the my swim field in the composite swimmer a struct. 05:34.190 --> 05:40.760 Now let's move to the composite underscore test dot go file and see the composite swimmer a struct. 05:40.760 --> 05:45.930 Have a look at this piece of code because we have a function called swim function. 05:45.980 --> 05:47.210 We can assign it to the. 05:47.300 --> 05:48.880 My swim field. 05:48.890 --> 05:53.580 Note that the swim type doesn't have the parenthesis that will execute its contents. 05:53.600 --> 05:57.970 This way we take the entire function and copy it to my swim method. 05:58.670 --> 06:06.060 But wait we haven't passed any athlete to the my athlete field and we are using it it's going to fail. 06:06.070 --> 06:07.480 That's weird isn't it. 06:07.480 --> 06:11.860 Not really because of the nature of zero initialization in go. 06:12.010 --> 06:17.680 If you don't pass an athlete struct to the composite swimmer a type the compiler will create one with 06:17.680 --> 06:19.870 its values zero initialized. 06:19.870 --> 06:24.900 That is an athlete struct with its fields initialized to 0. 06:24.910 --> 06:26.310 Check out Section 1. 06:26.320 --> 06:30.410 Ready steady go to recall 0 initialization. 06:30.460 --> 06:35.930 If this seems confusing consider the composite swimmer a struct code again. 06:36.040 --> 06:38.830 So let's go back to the composite dots go file. 06:38.830 --> 06:42.970 Now we have a pointer to a function stored and then my swim field. 06:42.970 --> 06:48.730 We can assign the swim function the same way but with an extra step let me show what this extra step 06:48.730 --> 06:51.800 is here where we have written the code for test. 06:51.820 --> 06:56.680 Let me remove the comments first we need a variable that contains the function. 06:56.740 --> 06:57.700 Swim. 06:57.700 --> 07:03.010 This is because a function doesn't have an address to pass it to the composite swimmer a type. 07:03.250 --> 07:08.910 Then to use this function within the struct we have to make a two step call. 07:08.930 --> 07:12.620 What about our fish problem with our swim function. 07:12.620 --> 07:14.440 It is not a problem anymore. 07:14.450 --> 07:16.840 First we create the animal struct. 07:16.970 --> 07:21.980 Then we create a shark object that embeds the animal object. 07:22.010 --> 07:23.450 Wait a second. 07:23.540 --> 07:26.210 Whereas the field name of the animal type. 07:26.210 --> 07:30.420 Did you realize that I used the word embed previously. 07:30.530 --> 07:37.760 This is because in go you can also embed objects within objects to make it look a lot like inheritance. 07:37.760 --> 07:43.700 That is we won't have to explicitly call the field name to have access to its fields and method because 07:43.790 --> 07:45.470 they'll be part of us. 07:45.530 --> 07:49.080 So this code will be perfectly okay. 07:49.130 --> 07:53.610 Now we have an animal type which is 0 initialized and embedded. 07:53.630 --> 07:59.840 This is why I can call the Eat method of the animal struct without creating it or using the intermediate 07:59.840 --> 08:01.220 field name. 08:01.220 --> 08:04.970 Finally there is a third method to use the composite pattern. 08:05.030 --> 08:11.660 We could create a swimmer interface with a swim method and a swimmer implement later type to embed it 08:11.660 --> 08:13.430 in the athletes swimmer. 08:13.430 --> 08:17.780 With this method you have more explicit control over object creation. 08:17.780 --> 08:24.080 The swimmer field is embedded but won't be 0 initialized as it is a pointer to an interface. 08:24.080 --> 08:27.580 The correct use of this approach will be this piece of code. 08:27.620 --> 08:29.210 Let's save this file. 08:29.210 --> 08:32.050 Move on to terminal and execute the command. 08:32.060 --> 08:37.180 Go test hyphen V and here's the output for composite swimmer B. 08:37.250 --> 08:40.330 As expected we got the output as training. 08:40.400 --> 08:43.850 Training and swimming eating and swimming. 08:43.850 --> 08:44.900 And the fourth one. 08:44.900 --> 08:46.490 Training and swimming. 08:46.670 --> 08:48.890 And we have passed the test. 08:48.980 --> 08:50.480 Which approach is better. 08:50.480 --> 08:55.640 Well I have a personal preference which shouldn't be considered the rule of thumb in my opinion. 08:55.640 --> 09:01.340 The interfaces approach is the best for quite a few reasons but mainly for explicitness. 09:01.340 --> 09:05.690 First of all you're working with interfaces which are preferred instead of struct. 09:05.690 --> 09:11.330 Secondly you aren't leaving parts of your code to the zero initialization feature of the compiler. 09:11.390 --> 09:17.270 It is a really powerful feature but one that must be used with care because it can lead to runtime problems 09:17.390 --> 09:23.600 which you'll find it compile time when working with interfaces in different situations zero initialization 09:23.600 --> 09:26.510 will save you at runtime in fact. 09:26.510 --> 09:29.810 But I prefer to work with interfaces as much as possible. 09:29.870 --> 09:33.010 So this is not actually one of the options. 09:33.080 --> 09:36.590 Now let's have a look at the binary tree compositions. 09:36.830 --> 09:42.110 So another very common approach to the composite pattern is when working with binary tree structures 09:42.620 --> 09:43.640 in a binary tree. 09:43.670 --> 09:47.200 You need to store instances of itself in a field. 09:47.210 --> 09:49.340 Here's how the code looks. 09:49.370 --> 09:55.700 This is some kind of recursive compositing and because of the nature of recursively we must use pointers 09:55.910 --> 10:00.070 so that the compiler knows how much memory it must reserve for this struct. 10:00.170 --> 10:07.950 Our tree struct stored a leaf value object for each instance and a new tree in its right and left fields. 10:07.990 --> 10:09.760 Let's go to composite test. 10:09.770 --> 10:12.270 Don't go with this structure. 10:12.290 --> 10:14.960 We could create an object like this. 10:14.960 --> 10:20.310 We can print the contents of its deepest branch as I've done here with this code line. 10:20.310 --> 10:26.840 Let's move to the terminal and execute this code so you can see that the test is passed and that we 10:26.900 --> 10:34.650 output 6 let's see composite pattern versus inheritance when using the composite design pattern and 10:34.650 --> 10:35.190 go. 10:35.190 --> 10:39.540 You must be very careful not to confuse it with inheritance. 10:39.540 --> 10:46.230 For example when you embed a parent struct within a son struct like in this example you cannot consider 10:46.230 --> 10:49.430 that the son struct is also the parent struct. 10:49.440 --> 10:55.110 What this means is that you cannot pass an instance of the son struct to a function that is expecting 10:55.110 --> 10:58.260 a parent struct like this piece of code. 10:58.560 --> 11:05.080 When you try to pass a son instance to get parent field method you will get this error message. 11:05.100 --> 11:11.180 This is a cannot use son as type parent in argument to get parent field. 11:11.220 --> 11:13.130 This in fact makes a lot of sense. 11:13.140 --> 11:14.820 What's the solution for this. 11:14.820 --> 11:16.910 Well you can simply compose it. 11:16.950 --> 11:23.790 The son struct with the parent without embedding so that you can access the parent instance later let's 11:23.880 --> 11:30.170 add P to the son struct and also make changes to get the parent field function call. 11:30.210 --> 11:35.670 So now you could use the P field to pass it to the get parent field method. 11:35.670 --> 11:37.480 Let's open composite test. 11:37.500 --> 11:38.620 Don't go. 11:38.730 --> 11:43.930 You can see we have used the p fields to pass it to the get to parent field method. 11:43.930 --> 11:47.790 Let's move to the terminal and here's the output for the test. 11:47.940 --> 11:54.240 Also at this point you should be really comfortable using the composite design pattern. 11:54.240 --> 12:01.330 It's a very idiomatic go feature and the switch from a pure object oriented language is not very painful. 12:01.350 --> 12:06.270 The composite design pattern makes our structure predictable but also allows us to create most of the 12:06.270 --> 12:11.600 design patterns as we will see in later sections in the next video. 12:11.630 --> 12:14.730 We will be learning about adapter design pattern.