Backend Development 12 min read

Applying Strategy, Factory Method, and Builder Patterns in Spring for Reward Distribution

This article explains how to implement the Strategy, Factory Method, and Builder design patterns within a Spring application to decouple reward‑distribution logic, showing interface definitions, concrete implementations, a factory for dynamic bean selection, and a prototype‑scoped builder for request construction.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Applying Strategy, Factory Method, and Builder Patterns in Spring for Reward Distribution

Design patterns such as Strategy, Factory Method, and Builder can make Spring‑based code more concise, extensible, and maintainable. The article demonstrates their usage through a reward‑distribution example.

1. Strategy Pattern

The Strategy pattern defines an interface with multiple implementations, each handling a specific case. In the example, public interface PrizeSender { boolean support(SendPrizeRequest request); void sendPrize(SendPrizeRequest request); } is the strategy interface.

Three concrete strategies are provided:

// PointSender implementation
@Component
public class PointSender implements PrizeSender {
    @Override
    public boolean support(SendPrizeRequest request) {
        return request.getPrizeType() == PrizeTypeEnum.POINT;
    }
    @Override
    public void sendPrize(SendPrizeRequest request) {
        System.out.println("发放积分");
    }
}
// VirtualCurrencySender implementation
@Component
public class VirtualCurrencySender implements PrizeSender {
    @Override
    public boolean support(SendPrizeRequest request) {
        return PrizeTypeEnum.VIRTUAL_CURRENCY == request.getPrizeType();
    }
    @Override
    public void sendPrize(SendPrizeRequest request) {
        System.out.println("发放虚拟币");
    }
}
// CashSender implementation
@Component
public class CashSender implements PrizeSender {
    @Override
    public boolean support(SendPrizeRequest request) {
        return PrizeTypeEnum.CASH == request.getPrizeType();
    }
    @Override
    public void sendPrize(SendPrizeRequest request) {
        System.out.println("发放现金");
    }
}

Each implementation declares @Component so Spring manages it as a bean, provides a support() method to decide if it can handle the request, and a sendPrize() method to perform the business logic.

2. Factory Method Pattern

The factory method encapsulates the selection of a concrete strategy. The PrizeSenderFactory scans all PrizeSender beans and returns the first one whose support() returns true.

@Component
public class PrizeSenderFactory {
    @Autowired
    private List
prizeSenders;

    public PrizeSender getPrizeSender(SendPrizeRequest request) {
        for (PrizeSender prizeSender : prizeSenders) {
            if (prizeSender.support(request)) {
                return prizeSender;
            }
        }
        throw new UnsupportedOperationException("unsupported request: " + request);
    }
}

The factory contains no knowledge of concrete classes, allowing new PrizeSender implementations to be added without modifying existing code.

A client example shows how to obtain a strategy and invoke it:

@Service
public class ApplicationService {
    @Autowired
    private PrizeSenderFactory prizeSenderFactory;

    public void mockedClient() {
        SendPrizeRequest request = new SendPrizeRequest();
        request.setPrizeType(PrizeTypeEnum.POINT);
        PrizeSender prizeSender = prizeSenderFactory.getPrizeSender(request);
        prizeSender.sendPrize(request);
    }
}

3. Builder Pattern

The Builder pattern is used to construct a complex request object while allowing Spring‑injected dependencies inside the builder. The inner static Builder class is marked with @Component and @Scope("prototype") so each build starts with a fresh instance.

public class SendPrizeRequest {
    private final PrizeTypeEnum prizeType;
    private final int amount;
    private final String userId;

    public SendPrizeRequest(PrizeTypeEnum prizeType, int amount, String userId) {
        this.prizeType = prizeType;
        this.amount = amount;
        this.userId = userId;
    }

    @Component
    @Scope("prototype")
    public static class Builder {
        @Autowired
        PrizeService prizeService;
        private int prizeId;
        private String userId;
        public Builder prizeId(int prizeId) { this.prizeId = prizeId; return this; }
        public Builder userId(String userId) { this.userId = userId; return this; }
        public SendPrizeRequest build() {
            Prize prize = prizeService.findById(prizeId);
            return new SendPrizeRequest(prize.getPrizeType(), prize.getAmount(), userId);
        }
    }
    // getters omitted for brevity
}

The client obtains a new builder from the Spring ApplicationContext , sets parameters fluently, and builds the request:

@Service
public class ApplicationService {
    @Autowired
    private PrizeSenderFactory prizeSenderFactory;
    @Autowired
    private ApplicationContext context;

    public void mockedClient() {
        SendPrizeRequest request = newPrizeSendRequestBuilder()
            .prizeId(1)
            .userId("u4352234")
            .build();
        PrizeSender prizeSender = prizeSenderFactory.getPrizeSender(request);
        prizeSender.sendPrize(request);
    }

    public SendPrizeRequest.Builder newPrizeSendRequestBuilder() {
        return context.getBean(SendPrizeRequest.Builder.class);
    }
}

4. Summary

The article uses a reward‑distribution scenario to illustrate how Spring can integrate the Strategy, Factory Method, and Builder patterns, highlighting key points such as bean registration with @Component , prototype scope for stateful builders, and decoupling of business logic from client code.

design patternsJavaSpringstrategyFactory MethodBuilder
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login 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.