Introduction
Strategy pattern (also known as the policy pattern) is a software design pattern that enables an algorithm’s behavior to be selected at runtime. It is based on the design principal Encapsulate what varies and Program to an interface, not an implementation. The strategy pattern
- Defines a family of algorithms,
- Encapsulates each algorithm, and
- Makes the algorithms interchangeable within that family.
Implementation
Instead of implementing a behavior the Context delegates it to State (current_state
). Strategy is implemented as interface so that we can change behavior without affecting Context. Context and the Strategy classes normally communicate through the interface specified by the abstract Strategy base class. In most cases, the application configures the Context with the required Strategy object.
Advantages
- A family of algorithms can be defined as a class hierarchy (ConcreteStateA and ConcreteStateB) and can be used interchangeably to alter application behavior without changing its architecture.
- By encapsulating the algorithm separately, new algorithms complying with the same interface can be easily introduced.
- The application can switch strategies at run-time.
- Data structures used for implementing the algorithm are completely encapsulated in Strategy classes. Therefore, the implementation of an algorithm can be changed without affecting the Context class.
Example
State (Strategy) – an interface that defines the behavior of a robot. Conctete Strategies: AggressiveBehaviour, DefensiveBehaviour, NormalBehaviour; each of them defines a specific behavior. Robot is the context class.
public interface State { public int DoSomething(); } public class AgressiveBehaviour implements State{ public int DoSomething() { System.out.println("Agressive Behaviour"); return 1; } } public class DefensiveBehaviour implements State{ public int DoSomething() { System.out.println("Defensive Behaviour"); return -1; } } public class NormalBehaviour implements State{ public int DoSomething() { System.out.println("Normal Behaviour"); return 0; } } public class Robot { State mBehaviour; String mName; public Robot(String name) { this.mName = name; } public void setBehaviour(State behaviour) { this.mBehaviour = behaviour; } public State getBehaviour() { return mBehaviour; } public void move() { // Implementation } public String getName() { return mName; } public void setName(String name) { this.mName = name; } } public class Main { public static void main(String[] args) { Robot r1 = new Robot("Big Robot"); Robot r2 = new Robot("R2"); r1.setBehaviour(new AgressiveBehaviour()); r2.setBehaviour(new DefensiveBehaviour()); r1.move(); r2.move(); // Behaviour changed r1.setBehaviour(new DefensiveBehaviour()); r2.setBehaviour(new AgressiveBehaviour()); r1.move(); r2.move(); } }