Difference Between Composite and Decorator Pattern – Design Patterns (ep 15)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back to the series on design patterns today we are going to talk about the difference between decorator pattern and composite pattern so the decorator pattern we've already talked about another specific video and the composite pattern we've already talked about in another specific video but in this video I want to talk about the sort of nuances and I'm going to talk about the differences between these because actually if you look at them they they look very very much the same but hopefully since they have two different names that they should turn out to be two different patterns and also by the way if you're new to this channel or to this playlist let me just mention that this is a playlist where we talk about all of the famous design patterns so we've already talked about tons of design patterns check out the playlist if you want to see any of those and we have tons left to go so subscribe so that you won't miss these anyways I did a bit of googling to try to figure out the sort of differences between decorator and composite pattern and it's not super clear and people have sort of different arguments for for the differences and a lot of the times it comes down to intent so the reason for using that particular pattern and then we often end up in the discussion of the composite pattern is useful when you have a structure that by its very nature is hierarchical or you have some piece of data that is that is susceptible to being modelled hierarchically in a sensible fashion or usefully whereas when we talk about decorator pattern we have situations where we want to be able to add runtime alter the behavior of some particular thing so an object is passed around in your application and at runtime you want to be able to change that particular thing or change the behavior of that particular thing without actually opening up the class and altering it so it's a way of supporting the open-closed principle from the solid object-oriented design principles if you want to know more about the solid design principles check out the link in the description for a playlist on that hopefully this would be a very short video I want to do three things first let's read the definitions of both of the patterns then let's look at both of the UML diagram side-by-side and then third let's talk about what in my mind seems to be like the key difference between composite and decorator or at least the one that I find interesting let's get started so I'll read the definitions from this book design patterns elements of reusable object-oriented software it's like the classic design patterns book by by Gang of Four which essentially means there are four authors and they're usually they note that as the Gang of Four super good book by the way if you want to know more about design patterns yes we cover a lot of stuff in this playlist but clearly there's a lot of more information in this book and also if you want something more pedagogical it may be get this book this book has more pictures and more funny jokes and all that headfirst design patterns this book also has examples in Java soul so that makes it a bit more accessible links to both of these books are in the description moving on but let's now read the definitions let's start with composite pattern so composite pattern composes objects into tree structures to represent part-whole hierarchies composite let's clients treat individual objects and compositions of objects uniformly so we're not going to dig into these definitions in details because as said before there are specific videos for both of these patterns so check out the links in the description for specific videos to these patterns but anyways just very quickly composite pattern is as we were saying before helpful when you have data that is multi-label as a hierarchy and the key point here is this last sentence composite let's clients in other words the user of your code structured within the composite design pattern the user of that code you let that person or that code base treat your objects and compositions of objects uniformly and if you have a look at the composition pattern video what we talked a bit about there is that this lets you eliminate an if-else branching so if you think about Martin Fowler's book refactoring there's this refactoring that he calls replace conditional with polymorphism essentially that's what happens in composite pattern if you have a tree of things then some things have some things and other things are leaves other things are in the end of the hierarchy let's just look at it this way if you have a tree of things this thing and this thing they all have subnodes but these things in the bottom these don't have some notes so they are fundamentally qualitatively different from these nodes above from these parent nodes that do have children so if you didn't use composite pattern you would probably use an if-else statement so that when you run an algorithm you would your algorithm would do one thing here and another thing here in other words one thing if it's in a node that has children and another thing if it's in a node that doesn't have children and that's the condition I'm talking about so when we use composite pattern we replace that conditional with polymorphism and that's what we achieved through a composite pattern but anyways now to the decorator pattern so the definition of the decorator pattern again from the same book the decorator pattern attaches additional responsibilities to an object dynamically decorators provide a flexible alternative to sub classing for extending functionality so this is a totally different story right if you go back to intent if we go back to why you would use this pattern so this pattern is trying to describe a situation to us where we have some kind of object and we want to be able to change the behavior of that object at runtime or more specifically in their words we want to be able to attach responsibilities we wanted to be able to do more things but we want to be able to do that dynamically so we don't want to open up the class and change the class so we want to do it at runtime but we don't want to do it using sub classing so we don't want to introduce another sub class because we want to have that compositionality we want to be able to mix and match different behaviors or different responsibilities so this is totally different story but we'll get into this in more detail before we move any further let's first look at the UML diagrams of both of them so let me remove this stuff let's just add a divider here let's say that composite is here and decorator is here now let's draw the UML diagrams so composite looks like this you've got a component and actually I'll do a very simplified version of UML just to save everyone I mean usually you draw this line here and then you have the public interface of that class but again since all of that information is in the other composite pattern video and in the decorator pattern video please check out those if you want more details but now we just want to sort of glance at the high-level structure of these two patterns like the question we're asking ourselves is are they structurally fundamentally different or are they actually the same rights because I mean intent can vary fine but it might be that intent varies and then they are exactly the same right then it's only intent but maybe it's also structure and that's what we're looking at now so we start off with a component and the component interface is implemented by two classes the leaf and the composite and the composite aggregates components the key portion here is let me say one too many so again without going into too much depth you have something which is called a component and both leaves and composites or components but leaves are essentially the end of the tree if you think about a tree you have a parent and then you have sub nodes and sub nodes so in other words you have a node that has two children and then these two children have two children of their own and then you can continue in this way and definitely when you get to the bottom this these nodes in the bottom these are needs because they don't have subsequent children all other nodes are parents so all other nodes are composites but these nodes in the end they're leaves so composites have components and this is how we get into this sort of recursion where a leaf and a composite both are components but composites have references to other components and since components can be components you can build an infinitely deep tree theoretically now let's draw the decorator so the decorator however also starts with the component come home and let me just remove this line for charity so it also starts with the component and it also has these two subclasses or implementers of the interface where this one we call a concrete component and this one we call a decorator and then the interesting portion is that the decorator aggregates components and at this point this is probably where you're feeling weight okay these are actually literally literally the same diagram except for the texts sorry I mean literally except also for this thing by the way they they don't draw so this is known as multiplicity in other words when I said one too many this is known as multiplicity so a composite can have components but the question is how many components can it have what's the least amount that it needs to have and what's the maximum amount that it can have so this is multiplicity so I I actually added this notion of the multiplicity I'm not sure in the head first book but surely and in this the design patterns book the Gang of Four book they don't actually draw out the multiplicity or that they don't actually specify the multiplicity sometimes it's done in UML sometimes it's not so so anyways I mean if you just take these portions at face value and you ignore this part that I add and they are literally the same these diagrams again except for the texts but I added this notion of the multiplicity in the composite because that's what we're doing with them with a composite but here's where we get into the subjective parts where I'm interpreting at what he actually intent of this pattern was for the intended structure anyways but that's not all right because I so far they are exactly the same but actually decorator is slightly different because there's a continuation here so the next step is that this decorator is also inherited from or implement that if it's an interface and I'll draw this sort of leaf on leaf notation here I don't mean leaf as in leaf from the composite I mean leaf as in paper leaf so I'm trying to in a 3d way draw that you have two different classes on top of each other just to emphasize that we can have multiple implementers of the decorator interface clearly I mean anytime you have multiple or anytime you have inheritance or interface implementation like this you can have multiples but just when we're drawing this I'm trying to emphasize that the intention is that this would completely vary based on your scenario and in your scenario you might end up with two decorators or 200 decorators both are valid in terms of the decorator pattern so this is just what I'm trying to denote here you might want multiple decorators but I'll only draw one because I mean there's no point in me drawing multiple ones for everyone's time so what do we call this well this we call a concrete decorator which sort of suggests to us that if this is a concrete decorator then this decorator class ought to be an abstract decorator similarly if this is a concrete component then this ought to be an abstract component and now you can see that they were actually different but I mean they're not hugely different right if you just think about it the only thing that's different now is that the class here in some sense is the same classes here right in the decorator pattern we call it the decorator and in the composite pattern we call it a composite because both of these inherit from the main component and both of these have an aggregation relationship with the component but the difference now is that we've said that okay this decorator isn't necessarily concrete or actually isn't concrete it's actually abstract and then there are concretions that inherit from this abstraction or implement this interface if it's an interface and that's the difference now I mean the reason we do this in decorator pattern is as far as I understand fairly practical it's it's simply because if you have so maybe before we go there let's just quickly recap what the decorator pattern does right the decorator pattern with the decorator pattern you have something so sorry I'm drawing it a composite and now but this belongs to the decorator pattern so you have a you have an instance of a component and then you wrap that component with decorators all right so all of these outer lines or decorators again please see that other decorator pattern video if you want to dig into more of what this means but the point is you have this component in the middle you have this concretions in the middle and then you wrap decorators around that concretions in order to attach additional behavior so that when somebody calls the outer shell of this decorator who decorates the decorator it decorates the decorator decorates the decorator decorates a component when somebody calls that outer shell the decorators call each other downwards in a chain and then the value propagates up which gives every decorator a chance to augment the value or augment the the action that the method forms if it's a void method that doesn't return anything but if you just think about something that returns something maybe this inner innermost component just returns returns the name and then one of the components capitalizes the name you know in other words make sure that the the first letter so in the first name and then in the last name are both capital letters and then maybe another one flips it so it's last name comma first name rather than the first name space last name or something like this right so these decorators alter the behavior of that method or attach additional responsibilities right if you think about title casing right upper casing the the first letters of both of the words and then that's an additional responsibility one responsibility is to extract the name from wherever you had the name and the second responsibility is to turn that into a title case string that's additional behavior anyways okay so if we then go back to the discussion around the decorator pattern of why the decorator pattern has this additional thing of concrete decorators inheriting from this decorator instead of just having multiple decorators so the reason if you think about it the decorator here is probably an abstract class and this abstract class is a component right it needs to be a component in order for decorators and concrete components to be interchangeable but the thing is that when you have instantiated a component and then wrap that with the decorator when you call the outer decorator let's say you call the decorated method then the decorator simply does whatever it needs to do like it attaches its additional behavior whatever its computation is and then passes the cold downwards to the component but for all of the non decorated methods it also needs to actually pass those methods down in other words if you have a scenario where the component that you have doesn't have just a single method instead if it has multiple methods but you're only interested in decorating one then that means that all the decorators need to pass the call to all those other methods downwards in the chain downwards towards the next decorator towards the next decorator and eventually down to the component so if I just draw this in two colors like let's say that the blue calls are calls to the method that we are intending to decorate but the green calls are calls to another method that we don't necessarily intend to to decorate but the component still needs to have it or you could even view it this way maybe some of the decorators decorate that other decorators simply just pass the message along then in this case we'll intercept the call but in this other case we'll just pass the call and the reason I'm saying that is that that would be the passing of the call that would be the responsibility of this abstract decorator class so in order to not have to redo that work in every concrete decorator because it's going to be the same work it's going to be the same simply just passing the message along to whoever I Magra gating so instead of redoing that work we put that in the decorator so that concrete decorators can focus on only the thing that they actually want to decorate and that's the reason for introducing that portion but I mean in my view I would then say that if you have a scenario where you don't have multiple methods and you're actually only decorating one then this would be somewhat superfluous of course clearly I missed one responsibility the other responsibilities of the decorator is that since decorators need to wrap something we clearly need a constructor in the decorator that accepts the thing that it needs to wrap so it accepts a component that could be another decorator or could be a concrete component and so the thing that it's wrapping taking that and assigning it to an instance variable within the decorator that's a responsibility for a decorator so that we won't have to do it in every concrete decorator but you know I mean again that could have been done in the concrete decorator and about that constructor I mean you could argue that the same goes for the composite it could argue now check out my composite pattern video for more information about that but the two books that I mentioned before and most of the resources on the internet go the route of talking about adding add and remove methods to the composite and then maybe you don't have exactly the same problem but I was suggesting that composite parent should more be understood in terms of a composite accepting a bunch of components through its constructor so that you don't have to mutate the component again please refer to that other video for more information about that but if you go that route that I'm suggesting then composite pattern becomes much like decorator pal I mean like if you look at the essence if you don't look at like all the tiny details it seems structurally they're actually very very equivalent but that leads me to the third and final point that I want to mention in this video what I actually subjectively find to be the key difference here is that I'm not really finding a lot of places where people suggest that you could have a decorator that decorates multiple components so remember we talked about multiplicity this means that the decorator decorates one to one component in other words it decorates one and only one component in other words a decorator must have a component in order for it to be a decorator it must decorate something must but it can only decorate a single thing like it can't decorate two things that's not a decorator so if I'm not mistaken the books I mentioned before and most of the researchers on the net don't necessarily suggest that it has to be one but like if you read between the lines it seems that that's the implicit suggestion and it seems that nobody's saying that well you could have a decorator that decorates multiple components and the way I read that is that the reason for that is that if you would have a decorator that decorates multiple components you wouldn't have the decorator pattern you would have the composite pattern because that's what the composite pattern does because as soon as your decorator decorates multiple components you're building a tree and that's the whole idea behind composite but again now we're very much into the notion of well should I call it this thing or should I call it this thing maybe it's mostly semantics and depending on your scenario you might want to call it one thing or the other in order to suggest to other developers what kind of madness you're you're up to so let me draw one final thing which I find particularly interesting that hopefully drives this point home let me remove this stuff but let me riad the divider and then we have composite here and decorator here so we already looked at how composite can be thought of as a tree before but let's draw one up again so you have a root node that references two children or rather you have a parent that references two children and let's say that these children reference to children and so forth and I mean we could go on but let's not do that and then because this is programming our nodes have references to other nodes so we need to think about which direction this reference goes into in other words if there's a relationship between nodes which node has a reference to the other node and clearly here the direction goes downwards so the parent has a reference to two children and each of the two children have references to two children but we don't have a relationship upwards or in other words the children don't have a direct reference upwards to the parents this is a key point if we look at the decorator pattern however remember that we said that decorators decorate a single component that means we're not building a tree what are we building well what we do is that we have a component and then we wrap that component within something else and then we wrap that component within something else and so forth and so forth and this notation I find is a bit more difficult and when you think about it this way right like when you have a node that's being wrapped by an O that's being wrapped by a node but in some sense I mean this is just exactly the same thing if you think about it what I did is just I move this here and then I move this here and then I move this here or something along those lines maybe it makes more sense to just so if you think about those as layers right it's like I had this node and then that node and then that no what I'm trying to draw it in 3d where they're sort of layered on top and then there's a reference between all these notes and then if you if you keep sort of tilting your head in this sort of 3d notation you'll end up with this node that references this other node that references this other node and then you can probably start to see how we end up here something along those lines but question number one then we have to ask ourselves about this relationship here is again what's the direction of the arrows here the direction was down but in this case the direction is actually up they make simplify because let's do it this way this node here is the component that node is the special node right think about it you have the base node and then you have the nodes that can have multiple nodes then the wrapping nodes so this is the base node and these are all wrapping nodes decorating notes and actually the same analogy holds for a composite pattern because you have leaves base nodes and then you have wrapping nodes which are parents which are composites and here these are the leaf nodes so in some sense then these bottom ones are the base notes and all of the other nodes all of the above nodes are wrapping notes our parent nodes are the sort of decorating nodes whereas in the decorator the top node is the sort of base normal base case node and all of the nodes below are the special wrapping nodes and this is where it really starts to get interesting but you might interject and say oh but but actually I mean this is completely silly because if I would just take its line and draw it in like literally the other direction if I would just spin it 180 degrees then the base node would also be in the bottom in the decorator picture and the arrows would point in the same direction as the composite so this proves nothing right clearly it doesn't but here's the reason I drew this in this direction hypothetically you could use the decorator pattern to build a tree even if you only allow a decorator to decorate a single thing this would look maybe I mean if I'm just adding another node this could look something like like this so I'm just adding another node so if you think about programming we have a reference to an object and when we draw these different adults are these different nodes what we mean or metaphorically what we're trying to talk about or references to memory locations references to objects in memory so this node is a location in memory all of these nodes are locations in memory they're objects in memory and if you have a reference to that location in memory if you have a reference to that object you can pass that reference to multiple places clearly so if I instantiate one concrete component and then I instantiate a decorator and pass the reference to this concrete component to this decorator so I wrap it but then what I can do is I can take the same concrete components so this I'm trying to say this is a different concrete component it's the same concrete component right is this right it's the reference to the same memory location to the same objective memory but then I wrap it in a different decorator let me do it this way to be super explicit I wrap it in a different decorator and then that's again to be super explicit let's draw this in the same color so it's the same inner component but I've wrapped it in two different decorators and then I can keep doing this I can wrap this concrete component again in another decorator or in another decorator but I could also take this out of these aggregations I could also take this decorator and wrap it in another decorator and take this other decorator and wrap it in another decorator which means that we can continue here in this tree so I wrap again here and that's actually if this is this black one corresponds to this one we need another line here so then we have two decorators around the component here and we have two decorators around the component here but they're all referencing the same concrete component and then we can keep doing this we can take any of these points any of these components and wrap it in another decorator we can wrap it in two different decorators simultaneously but create two different variables so maybe we wrap this in another decorator and that's for completion draw that as well so that would correspond to we have the concrete component and then we have the first decorator and then we have this second blue decorator and if I stop thinking about the colors for a moment you can hopefully see how we can create this tree this composite tree from this decorator tree if we don't think about the direction of the arrows so here I have if we express it using the same terms in the decorator case I have a root node a parent node with two children but only the right child has two children the left child only has one child so let's add another child to the left child actually let's stay consistent with the coloring so let's add that like so and then we can add another example down here that that corresponds to that example so we have the inner component the concrete component that's being wrapped by this first green decorator and then that first green decorator is being wrapped by this second red greater and now if you look at this tree and you compare it to this tree and if you don't think about the direction of the arrows they're the same you have a parent with two children where each of the two children have two children was actually the same but the interesting key differences are a the direction of the arrows in the decorator of the arrows are pointing upwards and in the composite the arrows are pointing downwards and also be that if you think about the base case everything about recursion in this industry the base case is either in the bottom or in the top so in the decorator pattern we have the base case here in the top but in the composite we have the base case here in the bottom now clearly in some sense if you would use decorator pattern as it was intended to be used I think we should think about the base case as being in the bottom because think about it this way in your code when you've constructed this this structure when you've constructed this object structure which object do you have a reference to well in the decorator pattern since you're decorating you would have a reference to one of these and in the composite pattern you would have a reference to this node so actually I mean in some sense this is the this is the the top of this tree as well so I'm kind of cheating maybe what we should do is that we should draw the arrows downwards as with this tree which would make it look like this instead where again the arrows are pointing downwards so that's of course an equivalent representation of this of the decorator tree that we have here so again then then the arrows are pointing downwards and the base case node is found in the bottom just as with the composite pattern but then you can see that we have two different tree structures so these are different ways of approaching the fact that they they are somehow different they are somehow sort of inverted if you start to think about decorating the same thing multiple times with multiple different decorators if you're actually actively trying to use the decorator pattern to build the tree now clearly again another objection that you might have to this is that of course if we allow ourselves to do that and the decorator I mean I'm not saying allow as if like that would be breaking some kind of rule but more as in that maybe we commonly wouldn't think about the decorator pattern as a tree but if we start to think about it as I didn't order just to discern the difference if we allow ourselves to do that in the decorator then I mean we could clearly allow ourselves to do that in the composite which means that we would introduce other composite nodes that contain or wrap in some sense other components which could be composite notes or which could be leaves which means that we suddenly end up in a scenario where we could build this for example or or this which means that if you start to think about it which means that the composite pattern can actually be used to build any tree that can be built using the decorator pattern but the decorator pattern can't be used to build any tree that the composite pattern can be used to build and of course I mean this is an it's nothing strange this is an inherent limitation of the fact that we've said that composites in the composite pattern can have references to multiple components while when a decorator is decorating something it can only decorate a single thing now I'm not entirely sure of what the practical value of this excursion is but maybe we could think about it this way firstly I mean of course parentheses I found it utterly interesting but anyways the concrete value we can draw from this is probably that if you have something that you think looks like a tree structure probably you need the composite pattern even if you start to think about weight I can actually use decorator pattern to build trees decorator pattern is not intended to be used to build trees decorator pattern is intended to be used to attach additional behavior to objects so you have a thing and you wrap it to attach additional behavior that's what we tend to call a decorator whereas a composite we actually use if we have something that we want to model as a tree structure but as you can see from this short excursion of looking at the different in the trees clearly they are very similar so I mean if we start to talk about a linked list for example write a list that's built up of a node referencing another node that's referencing another node that's referencing another node I mean this looks like the prototypical decorator pattern use case or example but maybe I would rather think of it as a composite because it's more about structure than it is about behavior it's more about constructing a list so it's not about matching up a bunch of different things in order to attach responsibility which is more what the decorator pattern is for but again if it's a linked list and every node only has a single reference to the next node so it's not like no that has a reference to two nodes so it's not actually a tree which means maybe we wouldn't call it a hierarchical structure but yeah I mean you could think of this as a hierarchical structure so then again we're back to intent and maybe that's the easiest way to think about this decorator is about attaching responsibilities at runtime you want to be flexible you can think about it in terms of composition you want to be able to compose different pieces of functionality while the composite pattern is about constructing hierarchies or maybe even a list of things that you want to be able to perform some particular algorithm upon but yeah they're pretty similar and I would say the two key differentiating factors are a the fact that we had another class in in the decorator and be the fact that we only allow the decorator to wrap a single other component and not multiple components whereas we didn't have that class in composite and whereas a composite can be a composite of multiple components but that's it I hope that makes sense and then you've now feel that you have some understanding of the differences between the composite pattern and the decorator pattern if you have any questions or comments please do shoot them in the comments and we can discuss and dig down further into this beyond that thank you super much for watching check out the description for links to both of the books remember to subscribe to stay tuned for more content like this we have tons of parents to go thank you again for watching and I will see you in the next one
Info
Channel: Christopher Okhravi
Views: 30,161
Rating: 4.9548874 out of 5
Keywords: composite pattern vs decorator pattern, difference between composite and decorator, composite vs decorator, difference, difference between, composite pattern, decorator pattern, composite, decorator, design patterns, design pattern
Id: EECfgFQ44Kg
Channel Id: undefined
Length: 31min 41sec (1901 seconds)
Published: Mon Dec 04 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.