Mastering Strategy and Factory Patterns in Spring Boot for Dynamic Advertising Pages

This article demonstrates how to replace complex if‑elseif logic with the Strategy pattern combined with simple and reflection‑based factories in a Spring Boot application, enabling clean, extensible handling of multiple advertising page types.

Programmer DD
Programmer DD
Programmer DD
Mastering Strategy and Factory Patterns in Spring Boot for Dynamic Advertising Pages

Application scenario: a third‑party interface returns four status strings (pdpAdvertisePage, plpAdvertisePage, shoppingCartAdvertisePage, checkoutAdvertisePage) that determine which advertising page to display.

First attempted solution used many if‑elseif statements, which became unreadable and was abandoned.

Second solution applies the Strategy pattern together with a simple factory, mapping each status to a concrete strategy class and making the logic clear.

Third solution replaces the simple factory with a reflection‑based factory, achieving the Open/Closed principle and allowing new page types to be added without modifying existing code.

public interface GetPointAdvertisePageStrategey {
    String getAdvertisePage(Model model);
}

Concrete strategy implementations:

@Component
public class PdpAdvertisePageStrategey implements GetPointAdvertisePageStrategey {
    @Override
    public String getAdvertisePage() {
        return "pdp-advertise.jsp";
    }
}
@Component
public class PlpAdvertisePageStrategey implements GetPointAdvertisePageStrategey {
    @Override
    public String getAdvertisePage() {
        return "plp-advertise.jsp";
    }
}
@Component
public class ShopingCartAdvertisePageStrategey implements GetPointAdvertisePageStrategey {
    @Override
    public String getAdvertisePage() {
        return "shoppingcart-advertise.jsp";
    }
}
@Component
public class CheckoutAdvertisePageStrategey implements GetPointAdvertisePageStrategey {
    @Override
    public String getAdvertisePage() {
        return "checkout-advertise.jsp";
    }
}

Simple factory that registers all strategies:

public class GetPointAdvertisePageSimpleFactory {
    public static final String PDP_ITEM_ADVERTISE = "PDP_ITEM_ADVERTISE";
    public static final String PLP_ITEM_ADVERTISE = "PLP_ITEM_ADVERTISE";
    public static final String CHECKOUT_ITEM_ADVERTISE = "CHECKOUT_ITEM_ADVERTISE";
    public static final String SHOPPINGCART_ITEM_ADVERTISE = "SHOPPINGCART_ITEM_ADVERTISE";
    private static Map<String, GetPointAdvertisePageStrategey> recommendStrategyMap = new HashMap<>();
    @Autowired private CheckoutAdvertisePageStrategey checkoutAdvertisePageStrategey;
    @Autowired private PdpAdvertisePageStrategey pdpAdvertisePageStrategey;
    @Autowired private PlpAdvertisePageStrategey plpAdvertisePageStrategey;
    @Autowired private ShopingCartAdvertisePageStrategey shopingCartAdvertisePageStrategey;
    protected void init() {
        recommendStrategyMap.put(PDP_ITEM_ADVERTISE, pdpAdvertisePageStrategey);
        recommendStrategyMap.put(PLP_ITEM_ADVERTISE, plpAdvertisePageStrategey);
        recommendStrategyMap.put(CHECKOUT_ITEM_ADVERTISE, checkoutAdvertisePageStrategey);
        recommendStrategyMap.put(SHOPPINGCART_ITEM_ADVERTISE, shopingCartAdvertisePageStrategey);
    }
    public GetPointAdvertisePageStrategey getStrategey(String pageType) {
        if (Validator.isNullOrEmpty(recommendStrategyMap)) { init(); }
        return recommendStrategyMap.get(pageType);
    }
}

Reflection‑based factory that creates strategy instances from a configuration file:

@Component
public class GetPointAdvertisePageReflectFactory {
    @Autowired private ApplicationContext context;
    private static final Logger LOGGER = LoggerFactory.getLogger(GetPointAdvertisePageReflectFactory.class);
    public GetPointAdvertisePageStrategey getAdvertisePageStrategey(String filePathName, String key) {
        try {
            String classPath = PropertyUtil.get(filePathName, key);
            if (Validator.isNullOrEmpty(classPath)) return null;
            Class<?> handler = Class.forName(classPath);
            return (GetPointAdvertisePageStrategey) context.getAutowireCapableBeanFactory()
                .createBean(handler, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
        } catch (Exception e) {
            LOGGER.error("Failed to reflect the corresponding object through the specified path, filePath:{},key:{}", filePathName, key);
            return null;
        }
    }
}

Utility class for reading properties files with caching:

public class PropertyUtil {
    private static Map<String, Properties> cache = new HashMap<>();
    public static String get(String configFileName, String key) {
        return getProperties(configFileName).getProperty(key);
    }
    public static Properties getProperties(String configFileName) {
        if (Validator.isNotNullOrEmpty(cache.get(configFileName))) {
            return cache.get(configFileName);
        }
        InputStream inputStream = PropertyUtil.class.getResourceAsStream(configFileName);
        Properties properties = new Properties();
        try { properties.load(inputStream); } catch (IOException e) { e.printStackTrace(); }
        cache.put(configFileName, properties);
        return properties;
    }
}

Test class showing how the reflection factory loads a strategy at runtime:

public class ItemRecommendReflectFactoryTest {
    private static final Logger LOGGER = LoggerFactory.getLogger(ItemRecommendReflectFactoryTest.class);
    @Autowired private GetPointAdvertisePageReflectFactory getItemRecommendStrategey;
    @Test
    public void refectFactoryTest() {
        String path = "/itemrecommend.properties";
        GetPointAdvertisePageStrategey strategy = getItemRecommendStrategey.getAdvertisePageStrategey(path, "pdp.item.advertise");
        if (Validator.isNotNullOrEmpty(strategy)) {
            LOGGER.info("Successfully obtained the strategy via configuration and reflection");
            LOGGER.info(strategy.getAdvertisePage());
        }
    }
}
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.

javaStrategy PatternSpring BootFactory Pattern
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.