Java programming language logo

Strategy Design Pattern

The Strategy pattern defines a set of interchangeable algorithms in separate classes and lets another object to change its behavior by replacing those algorithms at run-time.

This pattern can be used when the behavior of a class has to be changeable during run-time.

The behaviors are encapsulated into separate classes, but all implement a common interface. The client object that changes its behavior has a reference to a behavior object. When one of the client methods is called, that should have changeable behavior, it calls a method on the behavior object. Later the behavior object can be replaced, and when the same method is called again, it will have a different behavior.

Strategy is a behavioral pattern.

Example

This Java example is about a driver who changes driving styles as needed. Sometimes a little bit sporty, sometimes very careful. So a person has a driving behavior that changing.

First, we create an interface that defines the behavior.


package com.programcodex.designpatterns.strategy;

public interface DrivingBehavior {

    public void drive();
}

Next is to create a few implementations for it. These implementations will be replaced with each other during run-time.

The YouthfulDrivingBehavior class represents a kind of youthful driving style. It implements the DrivingBehavior interface.


package com.programcodex.designpatterns.strategy;

public class YouthfulDrivingBehavior implements DrivingBehavior {

    @Override
    public void drive() {
        System.out.println("I'm driving sporty...");
        System.out.println("...sometimes exceed the speed limit "
                + "and forget to use the indicator.");
    }
}

Old ladies are usually not in a hurry. They driving gently and carefully. This behavior is defined in the GrannyDrivingBehavior class.


package com.programcodex.designpatterns.strategy;

public class GrannyDrivingBehavior implements DrivingBehavior {

    @Override
    public void drive() {
        System.out.println("I'm driving like a granny...");
        System.out.println("...driving very slow...");
        System.out.println("...and there's always a line of cars behind me.");
    }
}

What if somebody cannot drive? In that case the driving behavior should be null? We don’t want to deal with null check. We create an implementation for that case too. The NoLicenseDrivingBehavior class also implements the DrivingBehavior interface.


package com.programcodex.designpatterns.strategy;

public class NoLicenseDrivingBehavior implements DrivingBehavior {

    @Override
    public void drive() {
        System.out.println("I have no driving license, so cannot drive.");
    }
}

Finally, let’s create a Person class that has a driving behavior stored in the drivingStyle field. The drive method uses this field, and its behavior depends on it. The default behavior is the NoLicenseDrivingBehavior.


package com.programcodex.designpatterns.strategy;

public class Person {

    private DrivingBehavior drivingStyle = new NoLicenseDrivingBehavior();
    
    public void setDrivingStyle(DrivingBehavior drivingStyle) {
        this.drivingStyle = drivingStyle;
    }

    public void drive() {
        drivingStyle.drive();
    }
}

And we are done. It’s time to run these things.

The Person class is instantiated, and its drive method gets called several times, but its behavior is changing between the calls because the setDrivingStyle method replaces its behavior instance after every call.


package com.programcodex.designpatterns.strategy;

public class TestStrategy {

    public static void main(String[] args) {
        Person johnny = new Person();
        
        System.out.println("Johnny, let's go somewhere.\n");
        johnny.drive();
        
        System.out.println("\nBut things changing. "
                + "Our man gets a license and some rutin.\n");
        johnny.setDrivingStyle(new YouthfulDrivingBehavior());
        johnny.drive();
        
        System.out.println("\nWatch out! A cop! Slow down!\n");
        johnny.setDrivingStyle(new GrannyDrivingBehavior());
        johnny.drive();
        
        System.out.println("\nThat was a close call. Let's move on.\n");
        johnny.setDrivingStyle(new YouthfulDrivingBehavior());
        johnny.drive();        
    }
}

The output of the above test class:

The Strategy Design Pattern