A guide to software design patterns
Structural Design Pattern: Decorator
The decorator pattern, one of the seven structural patterns, allows behavior to be added to an individual object, dynamically, without modifying the behavior of other objects from the same class.
The implementation of this pattern is also a good example of the single responsibility principle (S) of the S.O.L.I.D principles. It’s also very similar to the Chain Of Responsibility pattern with one major difference. In this pattern, all the classes handle the request while only one class handles the request in the chain of responsibility.
I’ve always found it easier to understand any new concept with a real-world scenario. Let’s use a real scenario and implement it using the decorator pattern.
Let’s say you work for a video game company and are tasked to create a character module. Because you will be working in parallel with another team, they request just the contract for now and will inject characters in their code as needed. A character should be able to display their available attacks. There is a basic character, which is the starting character, and as you level up in the game, characters also level up with additional attacks. Let’s see what that would look like in code.
We’ll start with an interface named “Character” with just one method: displayAttack(). The displayAttack() method will print the list of available attacks. The character interface looks like this:
public interface Character {
void displayAttack();
}Let’s start by creating a basic character that implements the character interface. To be creative, we’ll name the class CharacterImpl. The code looks like this.
public class CharacterImpl implements Character { @Override
public void displayAttack() {
System.out.println("basic attack...");
}
}This class will be used to build up the character as you level up in the game. So let’s create the decorator class now. We’ll name the class CharacterDecorator. The code looks like this:
public abstract class CharacterDecorator implements Character {
protected Character character;public CharacterDecorator(Character character){
this.character = character;
}@Override
public void displayAttack(){
this.character.displayAttack();
}
}I like martial arts movies, so let’s use martial arts to make this game interesting. Every time a character level up, we’ll decorate it with a new martial skill. Let’s create a few decorators each with specialized skills.
Here’s the code for the KungFuCharacter class:
public class KungFuCharacter extends CharacterDecorator {public KungFuCharacter(Character character) {
super(character);
}@Override
public void displayAttack() {
character.displayAttack();
displayFungFuAttack();}
private void displayFungFuAttack(){
System.out.println("kung fu attack...");
}
}Here’s the code for the TaeKwonDoCharacter class:
public class TaeKwonDoCharacter extends CharacterDecorator {public TaeKwonDoCharacter(Character character){
super(character);
}@Override
public void displayAttack() {
character.displayAttack();
displayTaeKwonDoAttack();}
private void displayTaeKwonDoAttack(){
System.out.println("tae kwon do attack...");
}
}Here’s the code for the KarateCharacter class:
public class KarateCharacter extends CharacterDecorator {public KarateCharacter(Character character) {
super(character);
}@Override
public void displayAttack() {
character.displayAttack();
displayKarateAttack();}
private void displayKarateAttack(){
System.out.println("karate attack...");
}
}Here’s the code for the JudoCharacter class:
public class JudoCharacter extends CharacterDecorator {public JudoCharacter(Character character) {
super(character);
}@Override
public void displayAttack() {
character.displayAttack();
displayJudoAttack();}
private void displayJudoAttack(){
System.out.println("judo attack...");
}
}The game starts with a character with only basic attacks. Let’s simulate leveling up and decorating the character for each level. We can use our decorator classes like this.
public static void main(String[] args) {
System.out.println("level 1...");
Character player = new CharacterImpl();
player.displayAttack();; System.out.println("\nlevel 2...");
Character kungfuDecorator = new KungFuCharacter(player);
kungfuDecorator.displayAttack(); System.out.println("\nlevel 3...");
Character karateDecorator = new KarateCharacter(kungfuDecorator);
karateDecorator.displayAttack(); System.out.println("\nlevel 4...");
Character judoDecorator = new JudoCharacter(karateDecorator);
judoDecorator.displayAttack(); System.out.println("\nlevel 5...");
Character taeKwonDoDecorator = new TaeKwonDoCharacter(judoDecorator);
taeKwonDoDecorator.displayAttack();
}The output looks like this:
level 1...
basic attack...level 2...
basic attack...
kung fu attack...level 3...
basic attack...
kung fu attack...
karate attack...level 4...
basic attack...
kung fu attack...
karate attack...
judo attack...level 5...
basic attack...
kung fu attack...
karate attack...
judo attack...
tae kwon do attack...As you can see, the output shows that the displayAttack() method is called in every class involved regardless of the order you add your decorators. We could use all of our decorators at once if we want to, it would look something like this.
//use multiple decorators at once.
//use all the decorator att once.
Character martialArtist = new KungFuCharacter(
new TaeKwonDoCharacter(
new KarateCharacter(
new JudoCharacter(
new CharacterImpl()
)
)
)
);martialArtist.displayAttack();The output would look like this:
basic attack...
judo attack...
karate attack...
tae kwon do attack...
kung fu attack...You can create and use as many decorators as you want. You have the flexibility to do so without having to worry about changing other objects.
This is, in a nutshell, the decorator pattern. Thank you for making it to the end. Happy coding.
Previous: Structural Design Pattern: Facade
