Eliminating Complex if‑else Logic with Strategy and Factory Patterns in a Spring‑Based Java Application
This article explains how excessive if‑else statements in business code hurt readability and maintainability, and demonstrates how to replace them with the Strategy and Factory design patterns integrated with Spring, using a food‑delivery discount example and complete Java code snippets.
In business development, growing requirements inevitably lead to tangled if‑else statements, which severely reduce code readability and maintainability.
The article first illustrates a realistic discount scenario for a food‑delivery platform, where multiple membership levels (exclusive, super, regular) and special conditions (order amount > 30, expired super membership) determine the final price. The original pseudocode contains deeply nested if‑else blocks, making the logic hard to follow.
To improve the situation, the Strategy pattern is introduced. An interface
public interface UserPayService { BigDecimal quote(BigDecimal orderPrice); }is defined, and three concrete strategy classes are provided:
public class ParticularlyVipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { if (orderPrice > 30) { return orderPrice.multiply(new BigDecimal("0.7")); } return orderPrice; } }<br/>public class SuperVipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { return orderPrice.multiply(new BigDecimal("0.8")); } }<br/>public class VipPayService implements UserPayService { @Override public BigDecimal quote(BigDecimal orderPrice) { if (userSuperVipJustExpired && !tempDiscountUsed) { tempDiscountUsed = true; return orderPrice.multiply(new BigDecimal("0.8")); } return orderPrice.multiply(new BigDecimal("0.9")); } }Using these strategies, the client code can simply instantiate the required strategy and call quote:
public class Test { public static void main(String[] args) { UserPayService strategy = new VipPayService(); BigDecimal quote = strategy.quote(new BigDecimal("300")); System.out.println("普通会员商品的最终价格为:" + quote.doubleValue()); strategy = new SuperVipPayService(); quote = strategy.quote(new BigDecimal("300")); System.out.println("超级会员商品的最终价格为:" + quote.doubleValue()); } }In a real Spring web project, beans are managed by the container, so the strategies are obtained from Spring instead of being instantiated manually. The article shows a factory class that stores strategy beans in 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) { Objects.requireNonNull(userType, "userType can't be null"); services.put(userType, service); } }The pricing method then becomes concise:
public BigDecimal calPrice(BigDecimal orderPrice, User user) { String vipType = user.getVipType(); UserPayService strategy = UserPayServiceStrategyFactory.getByUserType(vipType); return strategy.quote(orderPrice); }To automatically register each strategy bean, the classes implement InitializingBean and call the factory’s register method in afterPropertiesSet:
@Service public class ParticularlyVipPayService implements UserPayService, InitializingBean { @Override public BigDecimal quote(BigDecimal orderPrice) { if (orderPrice.compareTo(new BigDecimal("30")) > 0) { return orderPrice.multiply(new BigDecimal("0.7")); } return orderPrice; } @Override public void afterPropertiesSet() throws Exception { UserPayServiceStrategyFactory.register("ParticularlyVip", this); } }Similar implementations are provided for SuperVipPayService and VipPayService. During Spring’s startup, each strategy bean registers itself, allowing the factory to retrieve the correct implementation without any if‑else in the business logic.
The article concludes that combining Strategy, Factory, and Spring’s bean lifecycle dramatically improves code readability and maintainability, while also noting that the example simplifies some pattern concepts (e.g., missing Context in Strategy, factory used only for lookup). It encourages readers to focus on the underlying ideas of design patterns rather than strict textbook implementations.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
