Replacing if‑else with Strategy Pattern and Map‑Lambda in Java

This article demonstrates how to refactor coupon‑type dispatch logic by using the Strategy design pattern and a Map of Java 8 lambda expressions, showing code examples, trade‑offs, and a concise implementation that improves readability and maintainability.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Replacing if‑else with Strategy Pattern and Map‑Lambda in Java

Requirement

Service must return the grant type (distribution method) and claim rules for a coupon. Input fields: resourceType (coupon category) and resourceId (coupon identifier). Each resourceType maps to a different database table (e.g., red‑packet, shopping voucher, QQ membership, food‑delivery membership).

Problems with a naïve if‑else / switch

switch (resourceType) {
    case "红包":
        // query red‑packet grant type
        break;
    case "购物券":
        // query shopping voucher grant type
        break;
    case "QQ会员":
        // query QQ membership grant type
        break;
    case "外卖会员":
        // query food‑delivery membership grant type
        break;
    default:
        logger.info("Cannot find grant type for resourceType");
        break;
}

When each branch contains dozens of lines (database access, business validation, formatting), the method becomes long, hard to read and difficult to modify.

Strategy pattern

The Strategy pattern extracts each branch into a concrete class that implements a common interface. The client selects the appropriate strategy at runtime, so changes affect only the corresponding class.

Drawback: many small classes increase the code base and make it harder to see the overall dispatch logic.

Map + Java 8 functional interface

Store a Function<String,String> for each coupon type in a Map<String,Function<String,String>>. The map key is the resourceType; the value is a lambda that receives resourceId and returns the grant type.

@Service
public class QueryGrantTypeService {

    @Autowired
    private GrantTypeService grantTypeService;

    private final Map<String, Function<String,String>> grantTypeMap = new HashMap<>();

    /** Initialise the dispatch map – replaces the if‑else block */
    @PostConstruct
    public void init() {
        grantTypeMap.put("红包",   id -> grantTypeService.redPaper(id));
        grantTypeMap.put("购物券", id -> grantTypeService.shopping(id));
        grantTypeMap.put("QQ会员", id -> grantTypeService.qqVip(id));
        grantTypeMap.put("外卖会员", id -> grantTypeService.takeaway(id));
    }

    public String getGrantType(String resourceType, String resourceId) {
        Function<String,String> fn = grantTypeMap.get(resourceType);
        if (fn != null) {
            return fn.apply(resourceId);
        }
        return "查询不到该优惠券的发放方式";
    }
}

The concrete business logic can be isolated in a separate service:

@Service
public class GrantTypeService {

    public String redPaper(String resourceId) {
        // Example: query red‑packet table by resourceId
        return "每周末9点发放";
    }

    public String shopping(String resourceId) {
        // Example: query shopping voucher table
        return "每周三9点发放";
    }

    public String qqVip(String resourceId) {
        // Example: query QQ membership table
        return "每周一0点开始秒杀";
    }

    public String takeaway(String resourceId) {
        // Example: query food‑delivery membership table
        return "每日中午12点发放";
    }
}

Expose the service through a REST endpoint:

@RestController
public class GrantTypeController {

    @Autowired
    private QueryGrantTypeService queryGrantTypeService;

    @PostMapping("/grantType")
    public String getGrantType(@RequestParam String resourceType,
                               @RequestParam String resourceId) {
        return queryGrantTypeService.getGrantType(resourceType, resourceId);
    }
}

Pros and cons

Map + lambda provides a compact, visual mapping between coupon types and actions, avoiding a proliferation of classes.

Team members must be comfortable with Java 8 lambda syntax.

The Strategy pattern offers clearer separation when each branch contains extensive logic, but it can lead to many small classes.

Both approaches eliminate the long, hard‑to‑maintain if‑else chain.

Conclusion

Use the Strategy pattern when each coupon type requires substantial, independent processing and you prefer strict separation of concerns. Use the Map‑lambda approach for lighter‑weight dispatch logic, where the main goal is to keep the codebase small and the mapping easy to read. Choose the technique that matches the complexity of the business rules and the team's familiarity with functional programming.

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.

BackendDesign PatternsJavaStrategy PatternLambdaFunctional Interface
Java Architect Essentials
Written by

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.

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.