Mastering the Strategy Pattern: From Simple IF‑ELSE to Scalable Design
This article explains why hard‑coded if‑else logic hinders extensibility, introduces the Strategy pattern, shows its structure and Java implementation for data synchronization, then enhances the design with a Factory to decouple object creation, concluding with best‑practice recommendations.
Problem with if‑else for multiple external systems
In a project that exchanges data with several external systems, the initial implementation used a chain of if‑else statements to select the target system. As the number of integrations grew, the code became difficult to maintain, violated the Single‑Responsibility Principle and the Open/Closed Principle.
Strategy pattern
The Strategy pattern defines a family of interchangeable algorithms encapsulated in separate classes. A client can switch the concrete implementation at runtime without changing its own code.
Core structure
Define a strategy interface (or abstract class) that declares the operations required by all strategies.
Implement a concrete strategy class for each external system.
Create a context class that holds a reference to a DataProcessingStrategy and delegates calls.
In client code, instantiate the desired concrete strategy and pass it to the context.
Concrete example for data sync
public interface DataProcessingStrategy {
void receiveData();
void sendData(String data);
} public class ASystemDataProcessingStrategy implements DataProcessingStrategy {
@Override
public void receiveData() {
// implementation for system A
}
@Override
public void sendData(String data) {
// implementation for system A
}
} public class BSystemDataProcessingStrategy implements DataProcessingStrategy {
@Override
public void receiveData() {
// implementation for system B
}
@Override
public void sendData(String data) {
// implementation for system B
}
} public class Context {
private DataProcessingStrategy strategy;
public Context(DataProcessingStrategy strategy) {
this.strategy = strategy;
}
public void setStrategy(DataProcessingStrategy strategy) {
this.strategy = strategy;
}
public void sendData(String data) {
strategy.sendData(data);
}
public void receiveData() {
strategy.receiveData();
}
} public class Main {
public static void main(String[] args) {
Context context = new Context(new ASystemDataProcessingStrategy());
context.sendData("payload for A");
context.receiveData();
context.setStrategy(new BSystemDataProcessingStrategy());
context.sendData("payload for B");
context.receiveData();
}
}Limitations of a pure Strategy implementation
Hard‑coded dependencies: the client must know concrete strategy classes, so adding a new system requires code changes.
Tight coupling between client and concrete strategies increases maintenance effort.
Combining with the Factory pattern
Introduce a factory that registers and retrieves strategies by name, removing the need for the client to reference concrete classes.
public class DataProcessingStrategyFactory {
private static final ConcurrentHashMap<String, DataProcessingStrategy> strategies = new ConcurrentHashMap<>();
public static void register(String name, DataProcessingStrategy strategy) {
strategies.put(name, strategy);
}
public static DataProcessingStrategy getStrategy(String name) {
return strategies.get(name);
}
}Registration can be performed at application startup:
DataProcessingStrategyFactory.register("A", new ASystemDataProcessingStrategy());
DataProcessingStrategyFactory.register("B", new BSystemDataProcessingStrategy());Client usage:
public class Main {
public static void main(String[] args) {
DataProcessingStrategy a = DataProcessingStrategyFactory.getStrategy("A");
a.sendData("payload for A");
a.receiveData();
DataProcessingStrategy b = DataProcessingStrategyFactory.getStrategy("B");
b.sendData("payload for B");
b.receiveData();
}
}Takeaway
Applying the Strategy pattern eliminates repetitive conditional logic and makes the codebase extensible. Adding a factory further decouples client code from concrete implementations, reducing hard‑coded dependencies. Use these patterns judiciously to avoid unnecessary complexity.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
