6 Proven Strategies to Eliminate if‑else in Spring Boot Projects
This article explains why excessive if‑else statements hurt Spring Boot code and presents six practical techniques—including strategy pattern, enums, polymorphism, lambda expressions, command pattern, and guard clauses—along with complete Java examples to make your backend more modular, readable, and maintainable.
Environment: SpringBoot 3.2.5
Although if‑else statements are ubiquitous, overusing them can make code complex and hard to maintain. This article explores six strategies to reduce if‑else usage in Spring Boot projects, aiming for more modular, readable, and maintainable code.
The six optimization strategies are:
Strategy Pattern
Enum Usage
Polymorphism
Lambda Expressions & Functional Interfaces
Command Pattern
Guard Clauses
2. Practical Cases
2.1 Strategy Pattern
Define a strategy interface for payments:
<code>public interface PaymentStrategy {
void pay(double amount);
}</code>Implement different payment methods:
<code>@Component
public class WeiXinPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// TODO
System.out.printf("WeiXin pay %d%n", amount);
}
}
@Component
public class AliPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// TODO
System.out.printf("Ali pay %d%n", amount);
}
}
@Component
public class BankPayment implements PaymentStrategy {
@Override
public void pay(double amount) {
// TODO
System.out.printf("Bank pay %d%n", amount);
}
}</code>Define a payment service that injects all strategies:
<code>@Service
public class PaymentService {
private final Map<String, PaymentStrategy> paymentStrategies = new HashMap<>();
public PaymentService(List<PaymentStrategy> strategies) {
for (PaymentStrategy strategy : strategies) {
paymentStrategies.put(strategy.getClass().getSimpleName(), strategy);
}
}
public void processPayment(String strategyName, double amount) {
PaymentStrategy strategy = paymentStrategies.get(strategyName);
if (strategy != null) {
strategy.pay(amount);
} else {
throw new IllegalArgumentException(String.format("Unsupported payment method: %s", strategyName));
}
}
}</code>2.2 Enum Method
Use an enum to represent order states and their behavior:
<code>public enum OrderStatus {
NEW {
@Override
public void process() { /* TODO */ }
},
PAYING {
@Override
public void process() { /* TODO */ }
},
PAID {
@Override
public void process() { /* TODO */ }
},
SHIPPED {
@Override
public void process() { /* TODO */ }
};
public abstract void process();
}</code>Service that handles orders:
<code>@Service
public class OrderService {
public void processOrder(OrderStatus status) {
status.process();
}
}</code>2.3 Polymorphism
Define a notification interface and multiple implementations:
<code>public interface Notification {
void send(String message);
}</code> <code>@Component
public class EmailNotification implements Notification {
@Override
public void send(String message) {
// TODO: send email
}
}
@Component
public class SmsNotification implements Notification {
@Override
public void send(String message) {
// TODO: send SMS
}
}</code>Service that broadcasts messages to all notifications:
<code>@Service
public class NotificationService {
private final List<Notification> notifications;
public NotificationService(List<Notification> notifications) {
this.notifications = notifications;
}
public void notifyAll(String message) {
for (Notification notification : notifications) {
notification.send(message);
}
}
}</code>2.4 Lambda Expressions & Functional Interfaces
Use lambda expressions to define discount strategies:
<code>@Service
public class DiscountService {
private Map<String, Function<Double, Double>> discountStrategies = new HashMap<>();
public DiscountService() {
discountStrategies.put("VIP1", price -> price * 0.95);
discountStrategies.put("VIP2", price -> price * 0.90);
discountStrategies.put("VIP3", price -> price * 0.85);
discountStrategies.put("VIP4", price -> price * 0.80);
}
public double applyDiscount(String discountCode, double price) {
return discountStrategies.getOrDefault(discountCode, Function.identity()).apply(price);
}
}</code>2.5 Command Pattern
Define a command interface and concrete file operations:
<code>public interface Command {
void execute();
}</code> <code>@Component
public class OpenFileCommand implements Command {
private FileSystemReceiver fileSystem;
public OpenFileCommand(FileSystemReceiver fs) {
this.fileSystem = fs;
}
@Override
public void execute() {
fileSystem.openFile();
}
}
@Component
public class CloseFileCommand implements Command {
private final FileSystemReceiver fileSystem;
public CloseFileCommand(FileSystemReceiver fileSystem) {
this.fileSystem = fileSystem;
}
@Override
public void execute() {
fileSystem.closeFile();
}
}</code>Receiver interface and implementation:
<code>public interface FileSystemReceiver {
void openFile();
void closeFile();
}
@Service
public class UnixFileSystemReceiver implements FileSystemReceiver {
@Override
public void openFile() { /* TODO */ }
@Override
public void closeFile() { /* TODO */ }
}</code>Invoker that runs a command:
<code>@Component
public class FileInvoker {
private final Command command;
public FileInvoker(Command command) {
this.command = command;
}
public void execute() {
command.execute();
}
}</code>2.6 Guard Clause
Validate input early to keep the main logic clean:
<code>@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public void registerUser(User user) {
if (user == null) {
throw new IllegalArgumentException("User cannot be null");
}
if (!StringUtils.hasLength(user.getName())) {
throw new IllegalArgumentException("User name cannot be empty");
}
if (!StringUtils.hasLength(user.getEmail())) {
throw new IllegalArgumentException("User email cannot be empty");
}
userRepository.save(user);
}
}</code>Conclusion: Applying these six strategies can significantly reduce the use of if‑else statements in Spring Boot projects, resulting in cleaner, more efficient, and more maintainable code.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
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.