javaintermediate

Strategy Pattern with Lambdas

Implement the Strategy pattern using interfaces and Java lambdas for flexible algorithm selection.

java
import java.util.*;
import java.util.function.UnaryOperator;

// Strategy interface
@FunctionalInterface
interface PricingStrategy {
    double calculate(double basePrice, int quantity);
}

// Concrete strategies
class RegularPricing implements PricingStrategy {
    public double calculate(double basePrice, int quantity) {
        return basePrice * quantity;
    }
}

class BulkPricing implements PricingStrategy {
    public double calculate(double basePrice, int quantity) {
        double discount = quantity >= 100 ? 0.20 : quantity >= 50 ? 0.10 : 0;
        return basePrice * quantity * (1 - discount);
    }
}

// Context
class ShoppingCart {
    private PricingStrategy strategy;
    private final List<Item> items = new ArrayList<>();

    record Item(String name, double price, int quantity) {}

    public ShoppingCart(PricingStrategy strategy) {
        this.strategy = strategy;
    }

    public void setStrategy(PricingStrategy strategy) {
        this.strategy = strategy;
    }

    public void addItem(String name, double price, int qty) {
        items.add(new Item(name, price, qty));
    }

    public double total() {
        return items.stream()
            .mapToDouble(i -> strategy.calculate(i.price(), i.quantity()))
            .sum();
    }
}

public class StrategyDemo {
    public static void main(String[] args) {
        var cart = new ShoppingCart(new RegularPricing());
        cart.addItem("Widget", 10.0, 5);
        System.out.println("Regular: $" + cart.total()); // $50.0

        cart.setStrategy(new BulkPricing());
        System.out.println("Bulk: $" + cart.total()); // $50.0 (< 50 qty)

        // Lambda strategy — no class needed
        cart.setStrategy((price, qty) -> price * qty * 0.85); // 15% off
        System.out.println("Holiday: $" + cart.total()); // $42.5

        // Method reference as strategy
        cart.setStrategy(StrategyDemo::premiumPricing);
    }

    static double premiumPricing(double price, int qty) {
        return price * qty * 1.10; // 10% premium
    }
}

Use Cases

  • Swappable pricing or discount algorithms
  • Pluggable validation or sorting strategies
  • Runtime algorithm selection without if-else chains

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.