Your Guide to Design Patterns – Strategy Pattern

Design Patterns - Strategy Pattern

Last week we looked at one of the structural design patterns, the adapter pattern. This week we’ll look at the Strategy design pattern.

Strategy Pattern as a Behavioural Pattern

The Strategy pattern is a behavioural pattern. These are patterns that are concerned with communication between objects and encapsulating processes.

The intent of the Strategy pattern is to define a family of algorithms, encapsulate each one and make them interchangeable.

Strategy Pattern: Example

Let’s say we’re creating a first person shooter game. Amongst other things, the game will have monsters that can move through the modelled world, whether it is a maze, a building, a scorched Earth. These monsters can be aliens, zombies, robots, mutant creatures or anything else that we can think of. The monsters can hunt and attack the players. Obviously we should have a common Monster interface, which could be coded as follows:

public interface Monster {
    public void move();
    public void hunt();
}

We will code our concrete classes implementing this interface. Here is a snippet of code from the Zombie class; the others will be similar:

public class Zombie implements Monster {
    public void move() {
        // appropriate code
    }
    public void hunt() {
        // appropriate code
    }
}

The decision of how a monster can move or hunt can be based on the initial game level chosen by the player. This can also change as a player gets better and more skilled. This means we need to code up multiple different copies of the same monster for different skill levels. If we have a number of different monsters with the same way of moving and hunting, we’d have to do even more copying and pasting. A nightmare for testing and maintenance!

Strategy Pattern to the Rescue

A better way to model the movement and hunting mechanisms is to separate the algorithm for moving and hunting from that of the monsters themselves. We can then drop in a suitable movement algorithm whenever we create a monster. The algorithm itself will determine the movement. The first step is to create an appropriate interface for this algorithm:

public interface MovementStrategy {
    public void move() ;
    public void hunt() ;
}

We would then create a MovementStrategy instance field within a Monster, and delegate the movement and hunting to the contained object:

public class Zombie implements Monster {

    private MovementStrategy strategy;

    public Zombie(MovementStrategy strategy) {
        this.strategy = strategy;
    }
    @Override
    public void move() { 
        strategy.move();
    }
    @Override
    public void hunt() {
        strategy.hunt();
    }
} 

The intent of the Strategy design pattern is to define a family of interchangeable algorithms. This will allow the movement algorithm to vary independently from any of the classes that use it. We’ll create as many concrete classes implementing the MovementStrategy interface as necessary. Here are a few appropriately implemented concrete classes:

public class SlowShufflingMovement implements MovementStrategy {
    public void move() {
        // appropriate code
    }
    public void hunt() {
        // appropriate code
    }
}

public class FastHunterKillerMovement implements MovementStrategy {
    public void move() {
        // appropriate code
    }
    public void hunt() {
        // appropriate code
    }
}

When we create new monsters at the beginning of the game, or a new level, we can instantiate a class with the appropriate movement behaviours and pass it in to the monsters, as follows:

// Starting up the game; the level determines the movements
...
MovementStrategy strategy = new SlowShufflingMovement();
Monster zombie = new Zombie(strategy);
zombie.move();   // moves slowly

// OR
MovementStrategy strategy = new FastHunterKillerMovement();
Monster zombie = new Zombie(strategy);
zombie.move();   // moves fast

As you can see, this is relatively simple pattern to understand and implement.

What’s next?

In the weeks ahead, we’ll continue examining some of the more useful design patterns. Stay tuned!

I’m always interested in your opinion, so please leave a comment. Your feedback helps me write tips that help you.

Leave a Comment

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

Code like a Java Guru!

Thank You

We're Excited!

Thank you for completing the form. We're excited that you have chosen to contact us about training. We will process the information as soon as we can, and we will do our best to contact you within 1 working day. (Please note that our offices are closed over weekends and public holidays.)

Don't Worry

Our privacy policy ensures your data is safe: Incus Data does not sell or otherwise distribute email addresses. We will not divulge your personal information to anyone unless specifically authorised by you.

If you need any further information, please contact us on tel: (27) 12-666-2020 or email info@incusdata.com

How can we help you?

Let us contact you about your training requirements. Just fill in a few details, and we’ll get right back to you.

Your Java tip is on its way!

Check that incusdata.com is an approved sender, so that your Java tips don’t land up in the spam folder.

Our privacy policy means your data is safe. You can unsubscribe from these tips at any time.