“Decorator” pattern

With this pattern it is possible to dynamically assign new features to the desired object.

Let’s assume that we want to create a RPG game character which can be equipped with inventory like sword or armor. Each of this items has its own attack and defence points which increase attack and defence strength of our character. Let us create a warrior that has basic level of this points. With the use of the „Decorator” pattern we can enrich our object by wrapping it with additional objects.

Firstly, let’s create a basic class Character that has a method for getting description. It will show what was added to our object. Moreover, the class contains abstract methods for getting attack and defence points.

public abstract class Character {
    String description;

    public String getDescription() {
        return description;
    }

    public abstract int getAttackPoints();
    public abstract int getDefencePoints();
}

Secondly, we will create a Warrior class which will determine the basic points of our character.

public class Warrior extends Character {
    private int attackPoints = 5;
    private int defencePoints = 3;

    public Warrior() {
        description = "Warrior";
    }

    public int getAttackPoints() {
        return attackPoints;
    }

    public int getDefencePoints() {
        return defencePoints;
    }
}

The next step is to create an abstract class Inventory which contains a method that covers the one from the parent class.

public abstract class Inventory extends Character {

    public abstract String getDescription();
}

Now, let us create three classes representing our inventory:
1. Longsword

public class LongSword extends Inventory {
    private int attackPoints = 15;
    Character character;

    public LongSword(Character character) {
        this.character = character;
    }

    public String getDescription() {
        return character.getDescription() + ", longsword";
    }

    public int getAttackPoints() {
        return character.getAttackPoints() + attackPoints;
    }

    public int getDefencePoints() {
        return character.getDefencePoints();
    }
}

2. Steel armor

public class SteelArmor extends Inventory {
    private int defencePoints = 15;
    Character character;

    public SteelArmor(Character character) {
        this.character = character;
    }

    public String getDescription() {
        return character.getDescription() + ", steel armor";
    }

    public int getAttackPoints() {
        return character.getAttackPoints();
    }

    public int getDefencePoints() {
        return character.getDefencePoints() + defencePoints;
    }
}

3. Steel gloves

public class SteelGloves extends Inventory {
    private int defencePoints = 8;
    Character character;

    public SteelGloves(Character character) {
        this.character = character;
    }

    public String getDescription() {
        return character.getDescription() + ", steel gloves";
    }

    public int getAttackPoints() {
        return character.getAttackPoints();
    }

    public int getDefencePoints() {
        return character.getDefencePoints() + defencePoints;
    }
}

As we can see the methods in these classes are extending the description, as also increase attack and defence points of our character. Finally, having all required classes we can write the test code for the „Decorator” pattern.

public class DecoratorPatternTest {

    public static void main(String[] args) {
        Character begineerWarrior = new Warrior();
        System.out.println(begineerWarrior.getDescription() + '\n'
            + "Attack points: " + begineerWarrior.getAttackPoints() + '\n'
            + "Defence points: " + begineerWarrior.getDefencePoints() + '\n');

        Character intermediateWarrior = new Warrior();
        intermediateWarrior = new LongSword(intermediateWarrior);
        System.out.println(intermediateWarrior.getDescription() + '\n'
                + "Attack points: " + intermediateWarrior.getAttackPoints() + '\n'
                + "Defence points: " + intermediateWarrior.getDefencePoints() + '\n');

        Character advancedWarrior = new Warrior();
        advancedWarrior = new LongSword(advancedWarrior);
        advancedWarrior = new SteelArmor(advancedWarrior);
        advancedWarrior = new SteelGloves(advancedWarrior);
        System.out.println(advancedWarrior.getDescription() + '\n'
                + "Attack points: " + advancedWarrior.getAttackPoints() + '\n'
                + "Defence points: " + advancedWarrior.getDefencePoints() + '\n');
    }
}

Output text from the console:

Warrior
Attack points: 5
Defence points: 3

Warrior, longsword
Attack points: 20
Defence points: 3

Warrior, longsword, steel armor, steel gloves
Attack points: 20
Defence points: 26

 

Literature sources:
[1] Eric Freeman, Elisabeth Freeman, Kathy Sierra, Bert Bates – “Head First Design Patterns”.

Leave a Reply

Your email address will not be published. Required fields are marked *