Advertisment

Strategy Pattern

author-image
CIOL Bureau
Updated On
New Update

Satyabrata Dash, Harish

SK
and Avijeet Dash

Advertisment

Intent

Advertisment

Define a family of algorithms, encapsulate each one, and make them

interchangeable. Strategy lets the algorithm vary independently from clients

that use it.

In 30 Seconds

Advertisment

The catch here is "separate the invariant and variant behaviors of a

system". It enables one to break the design into two parts.

  • The "context" part of the design that deals with the behavior at

    an abstract level.  The behavior is thus referred to as the

    "strategy" for accomplishing a task. The context is the

    "invariant" part of the design in that its behaviors do not

    change from situation to situation.   Thus it can be

    encapsulated into a single object.
  • The "strategy" part of the design captures the

    "variant" nature of the design where the particular actions are

    chosen dynamically in the run time. The strategy section consists of an

    abstract strategy class and a series of concrete strategy

    subclasses.   Each subclass represents a possible specific action

    that could be taken when the strategy is executed by the

    context.    The variant nature of the design has been

    abstracted and captured in a tree hierarchy.
Advertisment

Motivation

Advertisment

Consider the implementation scenario when the client needs to choose an

algorithm out of various complex options available.

  • We can put all the business logic in the client class. The client will use

    conditional statements to choose an algorithm. It will make client code

    bigger and difficult to maintain when the logic is complicated and there are

    many variations of them.

Advertisment
  • The client can use subclassing of an object to implement the different

    behaviour in the subclass. But it will make the context tightly coupled to

    behaviour. So the object can’t dynamically change its behaviour.

  • Strategy pattern offers a solution to the above problems by decoupling the

    context from behaviour. It uses a Context class, which is responsible for

    maintaining and finding the behaviours. The ConcreteStrategy classes implement

    the algorithms that make the task to maintain code very easier. Whenever we

    need to add, delete or modify the algorithm, we can do so in respective

    ConcreteStrategy classes.
Advertisment

The strategy pattern, as the intent says, is, in short, a 'Pluggable

Algorithm'. For identifying a strategy pattern in a design in order that it can

be applied, it is necessary to first identify if an algorithm exists, and then

see whether the algorithm can be logically separated from the class, which is

intended to use it. The next step is to see whether the algorithm implementation

is expected to change later.

Let us take an example, assume a class responsible for calculating total

price of items in a shopping cart. The simplest implementation would be just

adding up the price of each item, which could be done by a simple method

calculatePrice(items); here we don't need any Strategy. Suppose there are

conditions to it like discount only for cat food only on Sundays, this involves

additional logic and just having a 'Rate of Discount' would not do. So, here we

have a 'Normal' price and 'Cat Discount' price, which is a situation that calls

for using the strategy pattern. We could then have a Strategy interface called

‘PricePolicy’, ‘NormalPricePolicy’ and ‘SundayCatPricePolicy’ would

be the concrete strategies. The Algorithm interface would be calculatePrice(

Item objects list). The default policy class could be NormalPricePolicy and

SundayCatPricePolicy be introduced only for Sundays.

Structure

Sample Code

Participants-



Context


It maintains a reference to Strategy object.


Strategy


It is an abstract class that declares the interface to all supported algorithm.


ConcreteStrategy


It implements the algorithm.


Client


It also knows about the ConcreteStrategy objects.






Example-



// Context class

class Context{
	private Strategy strategy= new ConcreteStrategyA(); //Default Algorithm

	public void changeStrategy(Strategy newStrategy){
		strategy=newStrategy;
	}

	public void getResult(){
		strategy.findAlgorithm();
	}
}

// Abstract Strategy class

abstract class Strategy{
	public abstract void findAlgorithm();
}

// ConcreteStrategyA class

class ConcreteStrategyA extends Strategy{
	public void findAlgorithm(){
		System.out.println("ConcreteStrategyA algorithm is used now");
	}
}

// ConcreteStrategyB class


class ConcreteStrategyB extends Strategy{
	public void findAlgorithm(){
		System.out.println("ConcreteStrategyB algorithm is used now");
	}
}		

//Client class
public class Client{

	public static void main(String args<>){
		Context ctx=new Context();
		ctx.getResult();
		ctx.changeStrategy(new ConcreteStrategyB());
		ctx.getResult();
	}
}		

Complexities simplified

Client knows different Strategies

Here the Client is exposed to various Strategy implementations. The Client

must know about all the patterns before selecting one. So the Client code must

be changed to accommodate any new algorithms introduced.

Communication overhead between Strategy and Context

All ConcreteStrategy classes share the same Strategy interface. So all of

them must implement the operations defined in the Strategy class even though

they may not need it. We can have a work around this by giving a default

implementation in the abstract class and let only the required classes over-ride

that default implementation.

State and Strategy pattern

Strategy pattern seems very similar to the State pattern. But they are

different. One difference is that Strategies are determined outside the Context

(passed to it by the client) while States are more internal (not accessible

outside the Context).

Nesting strategies

It is also possible that another strategy can be used within calculatePrice()

itself, we could use another strategy to get price of each item say

ItemPricePolicy. Instead of having a getPrice() for each item, we could set an

ItemPricepolicy for each item.

Also Known as and Related Patterns

It is also known as Policy.

The related patterns are

Adapter



The Adapter pattern is structurally similar to the Strategy pattern. The
difference is in the intent. The Adapter pattern allows a client object to carry

out its originally intended function by calling methods of objects that

implement a particular interface. The Strategy pattern provides objects that

implement a particular interface for the purpose of altering or determining the

behavior of a client object.

Flyweight



If there are many client objects, they may share strategy objects if they are
implemented as Flyweights.


Template

Method




The Template method pattern manages alternate behaviors through subclassing
rather than delegation.

Reference

Using

the Strategy Design Pattern to Compose Reliable Distributed Protocols




The Strategy Pattern Lab at Oberlin




Design Patterns in the Java AWT




Example of the Strategy Design Pattern




A Memory-Constrained Image-Processing Architecture

tech-news