Skip to the content.

Strategy

The problem

The shop runs different pricing rules at different times: loyalty discounts, bulk-order discounts, seasonal sales, sometimes none. Hard-coding them into the price calculator produces a growing if/else ladder that must be re-tested in full every time marketing invents a new promotion.

The pattern

Each rule is its own object behind one DiscountStrategy interface; the PriceCalculator context is configured with a rule rather than containing the rules:

PriceCalculator januarySale = new PriceCalculator(Discounts.seasonalSale(20));
PriceCalculator everyday = new PriceCalculator(Discounts.loyalty());

DiscountStrategy is a @FunctionalInterface, so a one-off promotion is just a lambda – which is how the pattern usually appears in modern Java (Comparator being the canonical example).

Benefits

Seen in the wild

Comparator (sorting strategy), ThreadFactory, Spring Security’s PasswordEncoder, Jackson’s PropertyNamingStrategy.

Implementation

Example test

PriceCalculatorTest