Strategy Pattern
In the Strategy Pattern, the behavior of a class or its algorithms can be changed at runtime. This type of design pattern falls under the category of behavioral patterns.
In the Strategy Pattern, we create objects that represent various strategies and a context object whose behavior varies as per its strategy object. The strategy object changes the execution algorithm of the context object.
Introduction
Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable.
Main Solution: When there are multiple algorithms similar to each other, using if...else conditions leads to complexity and difficult maintenance.
When to Use: When a system has many classes, and the only difference between them is their behavior.
How to Solve: Encapsulate these algorithms into separate classes and switch them as needed.
Key Code: Implement the same interface.
Example Applications: 1. Zhuge Liang's clever plans, each plan is a strategy.
- Travel methods, such as cycling or driving, each method is a strategy.
- LayoutManager in JAVA AWT.
Advantages: 1. Algorithms can be switched freely.
- Avoids multiple conditional statements.
- Good scalability.
Disadvantages: 1. Increases the number of strategy classes.
- All strategy classes need to be exposed.
Usage Scenarios: 1. When a system has many classes with differences only in their behavior, the Strategy Pattern allows dynamic selection of behavior for an object.
- When a system needs to dynamically choose between several algorithms.
- When an object has multiple behaviors, and these behaviors need to be implemented without using multiple conditional statements.
Notes: If a system has more than four strategies, consider using a hybrid pattern to address the issue of strategy class proliferation.
Implementation
We will create a Strategy interface defining an activity and concrete strategy classes implementing the Strategy interface. Context is a class that uses a strategy.
StrategyPatternDemo, our demo class, will use Context and strategy objects to demonstrate the change in Context's behavior based on the strategy it configures or uses.
Step 1
Create an interface.
Strategy.java
public interface Strategy {
public int doOperation(int num1, int num2);
}
Step 2
Create concrete classes implementing the interface.
OperationAdd.java
public class OperationAdd implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
OperationSubtract.java
public class OperationSubtract implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
OperationMultiply.java
public class OperationMultiply implements Strategy {
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
Step 3
Create the Context class.
Context.java
public class Context {
private Strategy strategy;
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
Step 4
Use Context to see the behavior change when it changes its Strategy.
StrategyPatternDemo.java
public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
Step 5
Execute the program, output results:
10 + 5 = 15
10 - 5 = 5
10 * 5 = 50