The decorator structural pattern allows you to add new behavior to object instances dynamically. That means an object can change its behavior at run time. The interesting thing is that your objects don’t even know they’ve been changed.
The episode describes a sword class with two methods: draw and strike.
If you want your game to have a cool sword with blue flames, then instead of subclassing the sword class and overriding methods, you can instead create a decorator class that just knows how to add blue flames. This might seem like inheritance. And it is because you’ll need some inheritance somewhere in order to get your decorator classes to mimic the classes they are decorating. But this pattern shows you how to use inheritance in a different way which will allow you to combine effects such as blue flames in interesting ways.
The important part is that a sword that is being decorated looks identical to the basic sword without any decorations. Each decoration composes an instance of what it thinks is the basic class. But because code can’t tell a basic class from a decorated class, it’s possible to chain decorations. The chaining is possible because of a critical aspect of writing a behavior. Each method in a decorator needs to call the composed method of the same name at some point. It might call the composed method first and then add something new, or add something new and then call the composed method. Or maybe it calls the composed method in the middle of adding something new. the important thing is that it does call the composed method. Because the object being decorated might actually be another decoration which will want to add its own behavior.
You can even double or triple your decorations. Or more. If you have a sword decoration that adds extra damage, then you can stack that damage by adding multiple extra damage decorations.
Listen to the episode for more about this pattern or read the full transcript below.
The basic description says that this pattern lets you attach additional responsibilities to an object dynamically which provides a flexible alternative to subclassing.
The biggest problem with inheritance is that the object relationships are setup at compile time. If you want an object to sometimes have different behavior and sometimes keep its current behavior, then inheritance is probably not the best choice. You should consider this decorator pattern.
Just to be clear, use inheritance when you want to change the behavior of all your instances of the new derived class. If you want different behaviors, you’ll need different derived classes.
And consider the decorator pattern when you want to add behavior. In a way, this can be seen as changing behavior. But, you’ll understand the intended purpose better if you think of this pattern as helping you to add new behaviors.
An example will help make this more understandable. In the adventure game that I like to use for examples, let’s say we need swords for weapons. Now this adventure game has lots of magic and enchantments. What happens if you enchant a sword?
First, we need to look at the basic class or interface that describes the basic sword. What are its methods? The public methods. For our example, let’s say there are only two methods, draw and strike. Maybe a real game will have more but these will work for this example.
What does it mean when you draw a sword? Simple, right? That’s just the action of grabbing the sword and pulling it out of its scabbard. Or pulling it out of the character’s belt if that’s all the character has available.
And strike means to swing the sword at an enemy and possibly do some damage.
Now, if you wanted to, you could create a blueFlameSword class that derived from the sword class and changed the draw method to know when to turn on some blue flame visual effects. This sword looks a lot more intimidating when the character starts swinging it.
But instead, I’m going to explain how to use the decorator pattern right after this message from our sponsor.
( Message from Sponsor )
By changing the way you think about this situation, it’s possible to go from modifying the draw method to turn on a blue flame effect to instead creating a decorator that adds a blue flame effect.
In the first solution that uses inheritance, the sword really is a blueFlameSword and knows all about the blue flame effect.
In the second solution, the sword remains just a simple sword and has no idea that it now looks a lot cooler.
Remember that I started this explanation by saying that we needed to look at the basic object interface. What the decorator pattern shows you is how to create a new class that mimics the basic type. The decorator should expose the exact interface as the object being decorated. The decorator class just forwards any calls to the original methods after or before doing anything additional.
This is important, because if we were using inheritance, then it’s common to override a method and never need to call the base class method.
The decorator pattern relies on the original method being called always. It does this by storing a reference to the original object. This is object composition. check out episode 28 for more information about composition.
And because the decorator mirrors the original interface and just forwards method calls, then there’s no need to override any methods. That means that this pattern works just fine even with classes that weren’t designed for inheritance.
When a blueFlameSword class is created, it just needs a pointer or reference to a sword object which it remembers. Then when some code calls the draw method, the blueFlameSword draw method will be the one called. That will call the plain sword’s draw method to do whatever it needs to do and then it will add the flame visual special effects to the sword.
All this is great and it gives you some flexibility but so far, you could just use inheritance, right? Well, here’s where things really get interesting. Because a decorator mimics the original interface, then that means when you provide the basic class to a decorator, who’s to say that this basic class isn’t already being decorated?
Sure, to do this, you’re going to need to use some inheritance. Don’t get me wrong. This pattern doesn’t describe how to avoid inheritance. It shows you how to use inheritance in a different way. You’ll want your decorator classes as well as the original basic class to all inherit from some common class or interface so that they’ll all be interchangeable. In other words, you should have some way to treat the basic class and a decorator class as if they were the same.
This gives you the ability to first start off with a basic sword that just knows how to draw and strike. You then create a blueFlameSword decorator and give it the basic sword as the object that it’s decorating.
Then what if you have an extra damage decorator? And what if you wanted to combine the extra damage with the blue flames? Simple. Just create an extraDamageSword decorator and pass it the blueFlameSword decorator as its basic object. The extraDamageSword decorator doesn’t know anything about blue flames. As far as it knows, all it’s doing is adding some extra damage whenever the sword strikes.
This is why the convention of always calling the basic class methods is so important. The extraDamageSword class has a draw method because that’s one of the basic class methods. But even though the extraDamageSword decorator doesn’t need to add anything to the draw method, it still needs to call draw.
Once you have these decorators, you can combine them as much as you want. For example, what if you wanted a double extra damage sword? You don’t need to create a doubleExtraDamageSword class. Just add as many decorations of the extraDamageSword decorator until you get the effect you want.
I’ll end this episode by comparing this pattern to the composite pattern described in the previous episode 66. The composite pattern also shows how to build elaborate objects in a flexible way at runtime. But where that pattern focuses on building more complex objects that can sometimes get quite large, this pattern focuses on just a single composition for each decorator. In a way is like a simple form of the composite pattern. But the difference is mainly one of intention. The decorator doesn’t intend to build a sword into a gigantic sword with many pieces that all fit together in a certain way. The decorator pattern instead intends to add a little something extra at each level. The decorator pattern focuses more on adding features and capabilities while the composite pattern focuses more on building complicated and elaborate structures.