Strategy Design Pattern

Design Pattern Tutorial Series

Strategy Design Pattern in Java - 5-Step Guide

The Strategy Pattern (aka. Policy Pattern), is perhaps one of the most simple design patterns of all. However, just because it is considerably simpler than other patterns does not mean that it is less valuable. Perhaps even the opposite. As a Behavioral Pattern, the strategy pattern provides objects with the ability to change their behavior (aka. strategy). 

Table of Contents

adapter-design-patterns-in-java-overview-INTEGU

Step 1 - The Objective

The general idea of the strategy pattern is to separate objects and their varying behaviors (aka. strategies) from each other by placing a layer of abstraction in between. 

Let’s take the example of the video. We have two objects, SquarePlate and HexagonPlate. Both objects are classes that extend the BasicPlate class, which is an abstract class. The objective is to provide the plate objects with a colored brick. The color of the brick will symbolize the strategy in this scenario. We want to have all combinations of plates and colored bricks available to runtime, but we are not sure which is the best approach.

We are therefore taking a look a two possible solutions: Class Inheritance and the Strategy Pattern.

strategy-design-pattern-objective-INTEGU

Step 2 – Class Inheritance

The initial Object-Oriented (OO) approach, is to create independent classes for all variations of the plates and colored bricks. Each class made this way would extend either SquarePlate or HexagonPlate and specify their brick’s color. At first sight, this solves the objective, but this approach also causes some problems.

Firstly, it is not possible to change the color of the brick after the code compiles. This is not an attractive behavior since we may want to add a color swapping feature in the future. Having the flexibility of changing the object’s strategy at runtime, is therefore valuable for us.

Secondly, it creates an exponentially growing number of classes. Currently, the amount of classes are contained to a low number. However, more plates and colored bricks might be added in the future. If this happens, it will quickly become a problem and developers will likely loose the overview.  

strategy-design-pattern-disadvantage-INTEGU
import java.util.ArrayList;


public class Main {

private static ArrayList allBooks = new ArrayList<>();

public static void main(String[] args) {

BookGroup businessBooks = new BookGroup("Business Books", "Business book can contain anything from leadership guidance to biographies.");
BookGroup technologyBooks = new BookGroup("Technology Books", "Technology book explain everything from programming to smartphones.");
BookGroup javaBooks = new BookGroup("Java Books", "Java books are used to learn the ways of the Java programming language.");

Book elonMuskBook = new Book("Elon", "Ashlee Vance");
Book extremeOwnershipBook = new Book("Extreme Ownership", "Jocko Willink");
Book androidPhonesForDummiesBook = new Book("Android Phones For Dummies", "Dan Gookin");
Book halloWorldBook = new Book("Hello World: How to be Human in the Age of the Machine", "Hannah Fry");
Book cleanCodeBook = new Book("Clean Code", "Robert c. Martin");
Book effectiveJavaBook = new Book("Effective Java", "Joshua Bloch");

businessBooks.add(elonMuskBook);
businessBooks.add(extremeOwnershipBook);

technologyBooks.add(androidPhonesForDummiesBook);
technologyBooks.add(halloWorldBook);

javaBooks.add(cleanCodeBook);
javaBooks.add(effectiveJavaBook);

allBooks.forEach(BookComponent::print);
}
}

Step 3 – Concept Of Strategy Pattern

As mentioned in the introduction, the idea of the strategy pattern is to provide a layer of abstraction in between the objects and the varying strategies. By having this layer of abstraction (Brick) we are able to specify to the objects (SquarePlate and HexagonPlate) what methods and/or object declarations to expect from their strategies (colored bricks). Meanwhile, the objects will not be aware of which specific strategy they are engaging with. We gain two advantages of this layer of abstraction:

Firstly, objects can modify at runtime, since they do not know which strategy they are engaging with. This allows us to swap in between strategies, due to the only requirement being that the strategy implements the same layer of abstraction. 

Secondly, we are not forced to have a class for each variation of objects and strategies. Due to the layer of abstraction, the classes become loosely coupled. This means that we only need to write a single instance of each object and strategy. 

strategy-design-pattern-advantage-INTEGU

Step 4 - Class Diagram (UML)

With the understanding of the Strategy Pattern’s concept, the question then becomes how to build it? We will answer this question by drawing the UML for the example and writing the code in Java. 

As a start, we know that the classes SquarePlate and HexagonPlate are extensions of the abstract BasicPlate class. 

In order to provide both plate classes with a colored brick, we declare that the BasicPlate class has a Brick. However, we do not instantiate or refer the declaration to anything inside the BasicPlate class. Then we also provide two concrete methods to BasicPlate. One for using the plates’ strategy (startBuilding) and one for swapping the strategy (setBrick). 

To build our layer of abstraction, we need to write a Brick interface. This interface only needs one strategy method for now (getColor). Using this interface as an implementation, we create one new class for each intended strategy. Each strategy class then overrides the strategy method from the interface and makes their unique functionality available through this method.

strategy-design-pattern-class-diagram-INTEGU

Step 5 - Code (Java)

Given that code is sometimes difficult to learn through concepts and theory, I provide the Java code for the example in both video and blog form. 

Hopefully, this will be sufficient for you to learn to identify and implement the Strategy Pattern in your future endeavors as a software developer.

The Object

abstract class BasicPlate {
    Brick brick;
    public void startBuilding(){
        System.out.println("I build with " + brick.getColor() + " bricks.");
    }
    public void setBrick(Brick brick) {
        this.brick = brick;
    }
}
class SquarePlate extends BasicPlate {
    public SquarePlate() {
        brick = new RedBrick();
    }
}

The Strategy

interface Brick {
    String getColor();
}
class RedBrick implements Brick {
    @Override
    public String getColor() {
        return "red";
    }
}

How To Use The Strategy Pattern

public static void main(String [] args) {       
        BasicPlate squarePlate = new SquarePlate();
        squarePlate.startBuilding();
        squarePlate.setBrick(new BlueBrick());
        squarePlate.startBuilding();
}

Recommended Reading

Articles

  • Theoretical walkthrough – Source Making – Blog
  • Practical walkthrough – Tutorialspoint – Blog
  • Practical walkthrough – Springframework Guru – Blog

Tools

  • Camtasia – Uses for illustrations and video – Camtasia

Books

Video Tutorial

  • Theoretical (based on “Head-First: Design Patterns”) – Christopher Okhravi – YouTube
  • Practical – Derek Banas – YouTube

About

Hi, I'm the Author

My name is Daniel H. Jacobsen and I’m a dedicated and highly motivated software developer with a masters engineering degree within the field of ICT. 

I have through many years of constantly learning and adapting to new challenges, gained a well-rounded understanding of what it takes to stay up to date with new technologies, tools and utilities. 

The purpose of this blog is to share both my learnings and knowledge with other likeminded developers as well as illustrating how these topics can be taught in a different and alternative manner.

If you like the idea of that, I would encourage you to sign up for the newsletter.

Cheers! 🍺

Didn't Find What You Were Looking For?

Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages
Scroll to Top