When If‑Else Gets Messy: Strategy Pattern vs. Map‑Based Dispatch in Java
The article compares a traditional if‑else/switch implementation with the Strategy pattern and a Map‑plus‑lambda approach for routing coupon‑type requests, showing each method’s code, advantages, drawbacks, and how to choose the most maintainable solution.
Problem Statement
A service must determine the grantType (distribution method) of a coupon based on two inputs: resourceType (coupon category) and resourceId (coupon identifier). The system currently has several tables (Red Packet, Shopping Coupon, QQ Membership, Takeaway Membership, etc.) and the naïve solution is a long if‑else or switch block.
Initial Switch Implementation
switch(resourceType){
case "红包":
// query red‑packet grant type
break;
case "购物券":
// query shopping‑coupon grant type
break;
case "QQ会员":
// …
break;
case "外卖会员":
// …
break;
default:
logger.info("Cannot find grant type for resourceType");
break;
}Although each case contains only one line in the example, real‑world logic spans many lines, making the method long, hard to read, and difficult to modify.
Issues with the Switch Approach
Low readability – a single method grows excessively.
Poor maintainability – adding a new coupon type requires editing a large block of code.
Strategy Pattern Solution
The Strategy pattern extracts each branch into its own class that implements a common interface. Changing a rule only requires editing the corresponding concrete class.
Structure (illustrated in the first image):
Example code:
switch(resourceType){
case "红包":
String grantType = new Context(new RedPaper()).ContextInterface();
break;
case "购物券":
String grantType = new Context(new Shopping()).ContextInterface();
break;
// ... other cases ...
default:
logger.info("Cannot find grant type for resourceType");
break;
}Drawbacks:
Each new resourceType requires a new concrete strategy class, leading to class explosion.
The overall dispatch logic remains hidden behind many classes, making it hard to view the whole flow at once.
Map + Functional Interface Approach
Java 8 lambda expressions allow the dispatch table to be expressed as a Map where the key is the coupon type and the value is a Function<String,String> that returns the grantType.
Advantages:
The condition ( resourceType) and the corresponding business logic sit side‑by‑side, giving a clear overview.
Adding a new type only means inserting a new entry into the map.
@Service
public class QueryGrantTypeService {
@Autowired
private GrantTypeService grantTypeService;
private Map<String, Function<String,String>> grantTypeMap = new HashMap<>();
/** Initialize the dispatch map, replacing the if‑else block */
@PostConstruct
public void dispatcherInit(){
grantTypeMap.put("红包", resourceId -> grantTypeService.redPaper(resourceId));
grantTypeMap.put("购物券", resourceId -> grantTypeService.shopping(resourceId));
grantTypeMap.put("qq会员", resourceId -> grantTypeService.QQVip(resourceId));
}
public String getResult(String resourceType, String resourceId){
Function<String,String> fn = grantTypeMap.get(resourceType);
if(fn != null){
return fn.apply(resourceId);
}
return "Cannot find grant type for this coupon";
}
}The concrete business logic is placed in a separate service class:
@Service
public class GrantTypeService {
public String redPaper(String resourceId){
return "Distribute every Sunday at 9 am";
}
public String shopping(String resourceId){
return "Distribute every Wednesday at 9 am";
}
public String QQVip(String resourceId){
return "Flash‑sale starts Monday 0 am weekly";
}
}A REST controller simply forwards the request:
@RestController
public class GrantTypeController {
@Autowired
private QueryGrantTypeService queryGrantTypeService;
@PostMapping("/grantType")
public String test(String resourceName, String resourceId){
return queryGrantTypeService.getResult(resourceName, resourceId);
}
}Second image (illustrating the map‑based flow):
Drawbacks of the Map approach:
Team members must understand lambda syntax; otherwise they may need to look up documentation.
Conclusion
The Strategy pattern improves maintainability by isolating each branch into its own class, but it introduces many classes and makes the overall dispatch view fragmented.
The Map‑plus‑lambda technique keeps the dispatch table compact and visible, reducing class count, yet it requires lambda proficiency.
Choosing between them depends on team skill set and the expected growth of coupon types: use Strategy when each branch has substantial, independent logic; use the Map approach when the logic is lightweight and you prefer a single, easily extensible table.
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.
Java Architect Essentials
Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.
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.
