在现代软件架构中,策略模式和工厂模式是两种非常实用的设计模式,它们可以提高代码的灵活性和可维护性。本文将结合这两种模式,介绍如何实现一个支持多种支付方式的支付系统。
一、背景介绍
在电子商务平台中,支付功能是核心功能之一。随着业务的发展,平台可能需要支持多种支付方式,如支付宝、微信支付、京东支付等。每种支付方式都有其特定的API和业务逻辑。为了应对这种多样化的需求,我们需要一个灵活且可扩展的支付系统设计。
二、策略模式
策略模式定义了一系列算法,将每个算法封装起来,让它们可以互换。这样,算法可以独立于使用它的客户端变化。
1. 定义支付策略接口
首先,我们定义一个支付策略接口,包含统一下单、退款、查询支付状态和关闭订单的方法。
package net.xdclass.component;
import net.xdclass.vo.PayInfoVO;
public interface PayStrategy {
String unifiedOrder(PayInfoVO payInfoVO);
String refund(PayInfoVO payInfoVO);
String queryPayStatus(PayInfoVO payInfoVO);
String closeOrder(PayInfoVO payInfoVO);
}
2. 实现具体策略
然后,为每种支付方式实现具体的支付策略。
package net.xdclass.component;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.vo.PayInfoVO;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class AliPayStrategy implements PayStrategy {
@Override
public String unifiedOrder(PayInfoVO payInfoVO) {
// 支付宝统一下单逻辑
return "支付宝下单成功";
}
@Override
public String refund(PayInfoVO payInfoVO) {
// 支付宝退款逻辑
return "支付宝退款成功";
}
@Override
public String queryPayStatus(PayInfoVO payInfoVO) {
// 支付宝查询订单状态逻辑
return "支付宝订单成功";
}
@Override
public String closeOrder(PayInfoVO payInfoVO) {
// 支付宝关闭订单逻辑
return "支付宝订单关闭成功";
}
}
package net.xdclass.component;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.vo.PayInfoVO;
import org.springframework.stereotype.Service;
@Service
@Slf4j
public class WechatPayStrategy implements PayStrategy {
@Override
public String unifiedOrder(PayInfoVO payInfoVO) {
// 微信统一下单逻辑
return "微信支付下单成功";
}
@Override
public String refund(PayInfoVO payInfoVO) {
// 微信退款逻辑
return "微信退款成功";
}
@Override
public String queryPayStatus(PayInfoVO payInfoVO) {
// 微信查询订单状态逻辑
return "微信订单成功";
}
@Override
public String closeOrder(PayInfoVO payInfoVO) {
// 微信关闭订单逻辑
return "微信订单关闭成功";
}
}
3. 支付策略上下文
为了更好地管理支付策略,我们可以使用Spring的@Service注解将策略类注册为Spring Bean。
package net.xdclass.component;
import net.xdclass.vo.PayInfoVO;
public class PayStrategyContext {
private PayStrategy payStrategy;
public PayStrategyContext(PayStrategy payStrategy) {
this.payStrategy = payStrategy;
}
public String executeUnifiedOrder(PayInfoVO payInfoVO) {
return payStrategy.unifiedOrder(payInfoVO);
}
public String executeRefund(PayInfoVO payInfoVO) {
return payStrategy.refund(payInfoVO);
}
public String executeCloseOrder(PayInfoVO payInfoVO) {
return payStrategy.closeOrder(payInfoVO);
}
public String executeQueryPayStatus(PayInfoVO payInfoVO) {
return payStrategy.queryPayStatus(payInfoVO);
}
}
三、工厂模式
工厂模式用于创建对象,而无需指定将要创建的对象的具体类。这样,客户端代码就可以与具体类解耦。
1. 定义支付工厂
定义一个支付工厂,根据支付类型创建对应的支付策略对象。
package net.xdclass.component;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.enums.ProductOrderPayTypeEnum;
import net.xdclass.vo.PayInfoVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class PayFactory {
@Autowired
private AliPayStrategy aliPayStrategy;
@Autowired
private WechatPayStrategy wechatPayStrategy;
/**
* 创建支付,简单工厂模式
* @param payInfoVO
* @return
*/
public String pay(PayInfoVO payInfoVO) {
String payType = payInfoVO.getPayType();
if (ProductOrderPayTypeEnum.ALI_PAY.name().equals(payType)) {
// 支付宝支付
PayStrategyContext payStrategyContext = new PayStrategyContext(aliPayStrategy);
return payStrategyContext.executeUnifiedOrder(payInfoVO);
} else if (ProductOrderPayTypeEnum.WECHAT_PAY.name().equals(payType)) {
// 微信支付
PayStrategyContext payStrategyContext = new PayStrategyContext(wechatPayStrategy);
return payStrategyContext.executeUnifiedOrder(payInfoVO);
}
return "";
}
/**
* 关闭订单
* @param payInfoVO
* @return
*/
public String closeOrder(PayInfoVO payInfoVO) {
String payType = payInfoVO.getPayType();
if (ProductOrderPayTypeEnum.ALI_PAY.name().equals(payType)) {
// 支付宝支付
PayStrategyContext payStrategyContext = new PayStrategyContext(aliPayStrategy);
return payStrategyContext.executeCloseOrder(payInfoVO);
} else if (ProductOrderPayTypeEnum.WECHAT_PAY.name().equals(payType)) {
// 微信支付
PayStrategyContext payStrategyContext = new PayStrategyContext(wechatPayStrategy);
return payStrategyContext.executeCloseOrder(payInfoVO);
}
return "";
}
/**
* 查询支付状态
* @param payInfoVO
* @return
*/
public String queryPayStatus(PayInfoVO payInfoVO) {
String payType = payInfoVO.getPayType();
if (ProductOrderPayTypeEnum.ALI_PAY.name().equals(payType)) {
// 支付宝支付
PayStrategyContext payStrategyContext = new PayStrategyContext(aliPayStrategy);
return payStrategyContext.executeQueryPayStatus(payInfoVO);
} else if (ProductOrderPayTypeEnum.WECHAT_PAY.name().equals(payType)) {
// 微信查询支付状态
PayStrategyContext payStrategyContext = new PayStrategyContext(wechatPayStrategy);
return payStrategyContext.executeQueryPayStatus(payInfoVO);
}
return "";
}
/**
* 退款接口
* @param payInfoVO
* @return
*/
public String refund(PayInfoVO payInfoVO) {
String payType = payInfoVO.getPayType();
if (ProductOrderPayTypeEnum.ALI_PAY.name().equals(payType)) {
// 支付宝支付
PayStrategyContext payStrategyContext = new PayStrategyContext(aliPayStrategy);
return payStrategyContext.executeRefund(payInfoVO);
} else if (ProductOrderPayTypeEnum.WECHAT_PAY.name().equals(payType)) {
// 微信退款
PayStrategyContext payStrategyContext = new PayStrategyContext(wechatPayStrategy);
return payStrategyContext.executeRefund(payInfoVO);
}
return "";
}
}
2. 支付上下文
支付上下文负责执行具体的支付操作,它持有一个支付策略对象,并调用其方法执行支付操作。
package net.xdclass.component;
import net.xdclass.vo.PayInfoVO;
public class PayStrategyContext {
private PayStrategy payStrategy;
public PayStrategyContext(PayStrategy payStrategy){
this.payStrategy = payStrategy;
}
/**
* 根据策略对象,执行不同的下单接口
* @return
*/
public String executeUnifiedOrder(PayInfoVO payInfoVO){
return payStrategy.unifiedOrder(payInfoVO);
}
/**
* 根据策略对象,执行不同的退款接口
* @return
*/
public String executeRefund(PayInfoVO payInfoVO){
return payStrategy.refund(payInfoVO);
}
/**
* 根据策略对象,执行不同的关闭接口
* @return
*/
public String executeCloseOrder(PayInfoVO payInfoVO){
return payStrategy.closeOrder(payInfoVO);
}
/**
* 根据策略对象,执行不同的查询订单状态接口
* @return
*/
public String executeQueryPayStatus(PayInfoVO payInfoVO){
return payStrategy.queryPayStatus(payInfoVO);
}
}
四、整合与测试
将上述组件整合到一起,并通过单元测试验证其功能。
1. 整合
在Spring Boot应用中,通过@Autowired自动装配上述组件。
2. 测试
编写单元测试,验证支付功能的正确性。
package net.xdclass.component;
import net.xdclass.vo.PayInfoVO;
import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
public class PayFactoryTest {
@Test
public void testPay() {
PayInfoVO payInfoVO = new PayInfoVO();
payInfoVO.setPayType("ALI_PAY");
payInfoVO.setOutTradeNo("123456");
payInfoVO.setPayFee(100L);
payInfoVO.setOrderPayTimeoutMills(30000L);
PayFactory payFactory = new PayFactory();
String result = payFactory.pay(payInfoVO);
System.out.println(result);
}
@Test
public void testCloseOrder() {
PayInfoVO payInfoVO = new PayInfoVO();
payInfoVO.setPayType("ALI_PAY");
payInfoVO.setOutTradeNo("123456");
payInfoVO.setPayFee(100L);
payInfoVO.setOrderPayTimeoutMills(30000L);
PayFactory payFactory = new PayFactory();
String result = payFactory.closeOrder(payInfoVO);
System.out.println(result);
}
}
五、总结
通过策略模式和工厂模式的结合,我们实现了一个灵活且可扩展的支付系统。每种支付方式都实现了一个具体的支付策略,而支付工厂负责根据支付类型创建相应的支付策略对象。这种设计不仅简化了客户端代码,还提高了系统的可维护性和可扩展性。
这种设计模式的结合使得在添加新的支付方式时,只需实现一个新的支付策略类并注册到支付工厂中,无需修改现有代码。同时,策略模式的使用也使得每种支付方式的业务逻辑独立,便于管理和维护。
在未来的发展中,可以进一步扩展支持更多的支付方式,如银联支付、PayPal等,只需增加相应的策略类即可。此外,还可以考虑引入配置中心,动态配置支付方式,以适应不断变化的业务需求。
503

被折叠的 条评论
为什么被折叠?



