Fundamentals 6 min read

Applying the Strategy Pattern with Simple Factory in a Java Backend Service

This article explains how to use the Strategy pattern combined with a simple factory in a Spring‑based Java backend, showing interface definition, multiple arithmetic strategy implementations, a factory that registers them in a map, a service that selects a strategy at runtime, and a REST controller for testing.

Architect's Guide
Architect's Guide
Architect's Guide
Applying the Strategy Pattern with Simple Factory in a Java Backend Service

Many developers are familiar with the Strategy pattern but may not know how to apply it in real projects; this article demonstrates its use when integrating a third‑party OA system that calls back different business interfaces based on a routing field.

First, a routing interface CalculationStrategy is defined, and concrete strategy classes (addition, division, multiplication, subtraction) implement this interface and are annotated with @Component so Spring can discover them.

public interface CalculationStrategy {
    /**
     * Strategy interface
     */
    int operate(int num1, int num2);
}

@Component("add")
class AddCalculationStrategyImpl implements CalculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1 + num2;
    }
}

@Component("Division")
class DivisionStrategyImpl implements CalculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1 / num2;
    }
}

@Component("multiple")
class MultiplicationStrategyImpl implements CalculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1 * num2;
    }
}

@Component("subtract")
class SubtractionStrategyImpl implements CalculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1 - num2;
    }
}

@Component
class TestStrategyImpl implements CalculationStrategy {
    @Override
    public int operate(int num1, int num2) {
        return num1 - num2;
    }
}

The second step is a factory (treated as a strategy context) that collects all @Component beans implementing CalculationStrategy and stores them in a Map<String, CalculationStrategy> for quick lookup.

@Component
public class CalculationFactory {
    /**
     * Put strategy key (bean name) and implementation into the map.
     */
    public final Map<String, CalculationStrategy> calculationStrategyMap = Maps.newHashMapWithExpectedSize(4);

    /**
     * Register all strategies at startup via constructor injection.
     */
    public CalculationFactory(Map<String, CalculationStrategy> strategyMap) {
        this.calculationStrategyMap.clear();
        this.calculationStrategyMap.putAll(strategyMap);
    }

    // Getter for service layer
    public Map<String, CalculationStrategy> getCalculationStrategyMap() {
        return calculationStrategyMap;
    }
}

Third, a service uses the factory to retrieve the appropriate strategy based on the incoming strategy string and executes the operate method.

@Service
public class CalculationService {
    @Autowired
    private CalculationFactory calculationFactory;

    public int operateByStrategy(String strategy, int num1, int num2) {
        // Potential null handling for missing strategy
        return calculationFactory.getCalculationStrategyMap().get(strategy).operate(num1, num2);
    }
}

Finally, a simple REST controller exposes an endpoint for testing the strategies, allowing callers to specify the operation name and two integers.

@RestController
@RequestMapping("/strategy")
public class TestStrategyController {
    @Autowired
    private CalculationService calculationService;

    @GetMapping("/test/{operation}/{num1}/{num2}")
    public int testCalculation(@PathVariable String operation, @PathVariable int num1, @PathVariable int num2) {
        // Parameter validation omitted for brevity
        return calculationService.operateByStrategy(operation, num1, num2);
    }
}

The main advantage of this design is extensibility: adding a new business branch only requires creating a new strategy implementation and annotating it with @Component; no other code changes are needed, making the system easy to maintain and evolve.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

BackendjavaStrategy Patternspringdependency-injectionFactory
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.