Mastering Strategy and Factory Patterns in Spring Boot for Flexible Payments
This tutorial shows how to combine the Strategy and Factory patterns in a Spring Boot payment system, separating algorithm definition, creation, and execution to achieve a flexible, extensible, and maintainable architecture that adheres to the Open/Closed principle.
Core Pattern Analysis and Collaboration Principle
Strategy pattern defines “what to do”, Factory pattern decides “who does it” and how to locate the implementation. Pairing them allows adding a new payment method (e.g., digital RMB) by creating a new strategy class and registering it in the factory, leaving existing business logic unchanged and satisfying the Open/Closed principle.
Order Payment Processing System
Step 1: Define the Strategy Interface
// PaymentStrategy.java
public interface PaymentStrategy {
/**
* Payment method
* @param amount payment amount
* @return payment result
*/
PayResult pay(BigDecimal amount);
/**
* Get strategy type for factory matching
* @return payment type
*/
String getType();
}Step 2: Implement Concrete Strategies
// AlipayStrategy.java
@Component
public class AlipayStrategy implements PaymentStrategy {
@Override
public PayResult pay(BigDecimal amount) {
// Simulate calling Alipay SDK
System.out.println("使用支付宝支付:" + amount + "元");
return new PayResult("SUCCESS", "支付宝支付成功", "ALIPAY_" + System.currentTimeMillis());
}
@Override
public String getType() {
return "ALIPAY";
}
}
// WechatPayStrategy.java
@Component
public class WechatPayStrategy implements PaymentStrategy {
@Override
public PayResult pay(BigDecimal amount) {
// Simulate calling WeChat Pay SDK
System.out.println("使用微信支付:" + amount + "元");
return new PayResult("SUCCESS", "微信支付成功", "WECHAT_" + System.currentTimeMillis());
}
@Override
public String getType() {
return "WECHAT";
}
}Step 3: Build the Strategy Factory
// PaymentStrategyFactory.java
@Component
public class PaymentStrategyFactory {
// Core: store all strategies, key is type, value is instance
private final Map<String, PaymentStrategy> strategyMap = new ConcurrentHashMap<>();
/** Constructor injection: Spring automatically injects all PaymentStrategy implementations into a List */
@Autowired
public PaymentStrategyFactory(List<PaymentStrategy> strategies) {
for (PaymentStrategy strategy : strategies) {
strategyMap.put(strategy.getType(), strategy);
}
// Print loaded strategies for debugging
System.out.println("支付策略工厂初始化完成,加载策略: " + strategyMap.keySet());
}
/** Retrieve strategy instance by payment type */
public PaymentStrategy getStrategy(String type) {
PaymentStrategy strategy = strategyMap.get(type);
if (strategy == null) {
throw new IllegalArgumentException("不支持的支付类型: " + type);
}
return strategy;
}
}Step 4: Use the Factory in Business Service
// OrderService.java
@Service
public class OrderService {
@Autowired
private PaymentStrategyFactory paymentStrategyFactory;
/** Create order and pay */
public PayResult createOrderAndPay(OrderRequest orderRequest) {
// 1. Create order (persistence omitted)
System.out.println("创建订单成功,订单号: ORD_" + System.currentTimeMillis());
// 2. Get payment strategy from factory
PaymentStrategy paymentStrategy = paymentStrategyFactory.getStrategy(orderRequest.getPaymentType());
// 3. Execute payment strategy
return paymentStrategy.pay(orderRequest.getAmount());
}
}Step 5: Expose API via Controller
// OrderController.java
@RestController
@RequestMapping("/api/order")
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping("/pay")
public ResponseEntity<PayResult> pay(@RequestBody OrderRequest orderRequest) {
PayResult result = orderService.createOrderAndPay(orderRequest);
return ResponseEntity.ok(result);
}
}Auxiliary Class Definitions
// OrderRequest.java (API request body)
@Data
public class OrderRequest {
private String paymentType; // e.g., "ALIPAY"
private BigDecimal amount; // payment amount
}
// PayResult.java (payment result)
@Data
public class PayResult {
private String status; // e.g., "SUCCESS"
private String message; // description
private String transactionId; // transaction ID
public PayResult(String status, String message, String transactionId) {
this.status = status;
this.message = message;
this.transactionId = transactionId;
}
}Start the Spring Boot application with the above code. Send a POST request to /api/order/pay with JSON body:
POST /api/order/pay
Content-Type: application/json
{
"paymentType": "ALIPAY",
"amount": 299.99
}The backend prints “使用支付宝支付:299.99元” and returns a JSON‑formatted PayResult.
Strategy Pattern decouples algorithms, enabling flexible addition or replacement of payment logic.
Factory Pattern decouples creation, centralizing lifecycle management and lookup of strategies.
Combined, they provide interface‑driven programming and dependency injection, yielding highly configurable and extensible business logic for complex branching scenarios.
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.
Senior Xiao Ying
Dedicated to sharing Java backend technical experience and original tutorials, offering career transition advice and resume editing. Recognized as a rising star in CSDN's Java backend community and ranked Top 3 in the 2022 New Star Program for Java backend.
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.
