Strategy Pattern

Strategy pattern is a behavioral design pattern that enables an algorithm to select it's at runtime. This pattern is also known as Policy Pattern.

Design Patterns by Gamma et al. that popularized the concept of using patterns to describe software design has mentioned the intent of this pattern as, the strategy pattern

  • defines a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from the clients that use it.
  • captures the abstraction in an interface, bury implementation details in derived classes.

 

Structure

The following diagram shows the structure of strategy pattern.

strategy-pattern

Figure: Structure of Strategy Pattern​

 

Example

Let us consider a simple case where we want to draw different geometric shapes. This has been depicted on the class diagram below:

strategy-pattern-ex0

Figure: Class Diagram for Drawing Shapes

If you call drawLine() from the Application class, then the drawLine of the DrawingCanvas gets called, and a line is drawn on the canvas.

An disadvantage of the given drawing application is that it only draws lines, circles and rectangles, and if we also want to draw triangles, we have to change the code of the DrawingCanvas class. 

In order to be able to add new shapes to the drawing program without changing the code at DrawingCanvas, we can use strategy pattern and redraw the class diagram as below:

strategy pattern example

Figure: Strategy Pattern Example

Here, we can add any number of classes that can draw the shape as per our need.

 The following sequence diagram shows how the strategy pattern works to draw a line and a circle.

strategy pattern example sequence

Figure: Sequence diagram to draw a line and a circle

 

Java implementation

Let us first define an interface that represent strategy in pattern.

/**
 * it represents the strategy ( abstraction level)
 */
public interface DrawingStrategy {
    void draw();
}

Now, lets create the concrete implementation of this strategy.

/**
 * It is implementation of abstract Strategy
 * i.e. it is concrete strategy
 */
public class DrawLine implements DrawCanvas {
    public void draw() {
        System.out.println("Line Drawn.");
    }

}
/**
 * It is implementation of abstract Strategy
 * i.e. it is concrete strategy
 */
public class DrawRectangle implements DrawCanvas {
    public void draw() {
        System.out.println("Rectangle drawn.");
    }
}
/**
 * It is implementation of abstract Strategy
 * i.e. it is concrete strategy
 */
public class DrawCircle implements DrawCanvas {
    @Override
    public void draw() {
        System.out.println("Circle Drawn.");
    }

}

Now, lets create the context in which we define the strategy what geometric shape we want to draw.

/**
 * Context
 */
public class DrawingCanvas {
    private DrawingStrategy strategy;
    public void drawGeometricShape(){
        strategy.draw();
    }
    public void setStrategy(DrawingStrategy strategy){
        this.strategy = strategy;
    }
}

The following code snippet represents a client for our application.

/**
 * it represents a client for this example.
 */
public class Application {

    public static void main(String[] args) {
        DrawingCanvas canvas = new DrawingCanvas();
        //drawing a line
        canvas.setStrategy(new DrawLine());
        canvas.drawGeometricShape();
        //drawing a circle
        canvas.setStrategy(new DrawCircle());
        canvas.drawGeometricShape();
        //drawing a rectangle
        canvas.setStrategy(new DrawRectangle());
        canvas.drawGeometricShape();
    }
}

The output of the program is:

Line Drawn.
Circle Drawn.
Rectangle drawn.

The output of the program illustrates that client can create a context defining the requirement. Then, strategy will determine which concrete implementation should be invoked at runtime.

Observer Pattern
Facade Pattern