Eliminating Complex if‑else Logic with Strategy and Factory Patterns in Spring

This article explains how to replace tangled if‑else statements in business code with the Strategy and Factory design patterns, demonstrates their implementation in Java and Spring, and shows how to register strategy beans to improve readability and maintainability.

Java Captain
Java Captain
Java Captain
Eliminating Complex if‑else Logic with Strategy and Factory Patterns in Spring

Business logic often becomes tangled with numerous if‑else branches as requirements grow, hurting readability and maintainability. The article starts with a realistic ordering‑platform scenario where different membership levels require distinct discount calculations, leading to deeply nested conditional code.

To address this, the author introduces the Strategy pattern: an interface UserPayService defines a quote method, and separate strategy classes ( ParticularlyVipPayService, SuperVipPayService, VipPayService) implement the specific discount logic.

public interface UserPayService {
    public BigDecimal quote(BigDecimal orderPrice);
}

public class ParticularlyVipPayService implements UserPayService {
    @Override
    public BigDecimal quote(BigDecimal orderPrice) {
        if (orderPrice > 30) {
            return price * 0.7; // 7折
        }
        return null;
    }
}

public class SuperVipPayService implements UserPayService {
    @Override
    public BigDecimal quote(BigDecimal orderPrice) {
        return price * 0.8; // 8折
    }
}

public class VipPayService implements UserPayService {
    @Override
    public BigDecimal quote(BigDecimal orderPrice) {
        if (userJustExpired && !tempDiscountUsed) {
            // update usage count
            return price * 0.8; // 8折
        }
        return price * 0.9; // 9折
    }
}

Using these strategies, client code can simply obtain the appropriate implementation and call quote, eliminating most conditional branches.

However, directly instantiating strategy objects is unsuitable for a Spring‑managed web application. The article therefore adds a Factory class that holds a Map<String, UserPayService> and provides getByUserType and register methods.

public class UserPayServiceStrategyFactory {
    private static Map<String, UserPayService> services = new ConcurrentHashMap<>();
    public static UserPayService getByUserType(String type) { return services.get(type); }
    public static void register(String userType, UserPayService service) { services.put(userType, service); }
}

Each strategy class implements InitializingBean and registers itself in afterPropertiesSet, so Spring automatically populates the factory during bean initialization.

@Service
public class ParticularlyVipPayService implements UserPayService, InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        UserPayServiceStrategyFactory.register("ParticularlyVip", this);
    }
    // quote implementation …
}

Finally, the price‑calculation method becomes a clean one‑liner:

public BigDecimal calPrice(BigDecimal orderPrice, User user) {
    String vipType = user.getVipType();
    UserPayService strategy = UserPayServiceStrategyFactory.getByUserType(vipType);
    return strategy.quote(orderPrice);
}

The article concludes that while the example simplifies the classic GOF definitions, the key takeaway is the practical combination of Strategy, Factory, and Spring bean registration to dramatically improve code clarity and extensibility.

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.

Design PatternsJavaStrategy PatternspringFactory Pattern
Java Captain
Written by

Java Captain

Focused on Java technologies: SSM, the Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading; occasionally covers DevOps tools like Jenkins, Nexus, Docker, ELK; shares practical tech insights and is dedicated to full‑stack Java development.

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.