设计模式之策略+工厂实现支付功能代码优化

源码地址:支付设计模式优化

背景

在我们开发中支付功能可能遇到的不少,今天这个案例就是以支付为中心,通过结合设计模式实现支付功能的扩展性。方便我们以后需求增加、变更的时候是我们开发起来得心应手,同时也减少QA的回归时间。

设计关系图

在这里插入图片描述

实现类

接口基类

/**
 * @ClassName IPay
 * @Description 支付接口
 * @Author xiaowu
 * @Date 2021/8/10 6:02 下午
 */
public interface IPayStrategy<T> {

    /**
     *  支付
     * @param payBusiness
     * @return
     * @throws Exception
     */

    Result pay(PayBusiness<T> payBusiness) throws Exception;

    Logger logger = Logger.getLogger(IPayStrategy.class.getName());

}

策略控制类

/**
 *
 * @ClassName ContextHandler
 * @Description: 策略控制
 * @Author xiaowu
 * @Date 2021/8/10
 * @Version V1.0
 **/
public class ContextStrategy<T> {

    private IPayStrategy<T> pay;

    public ContextStrategy(IPayStrategy<T> pay) {
        this.pay = pay;
    }

    public Result payProcess(PayBusiness<T> t) throws Exception {
        return pay.pay(t);
    }
}

工厂类

通过init 方法加载实现类的class 路径,注册实现到本地缓冲中,方便策略控制类获取具体实现类对象。


/**
 * @ClassName PayStrategyFactory
 * @Description: 支付策略工厂类
 * @Author 小五
 * @Date 2021/8/10
 * @Version V1.0
 **/
public class PayStrategyFactory {
    private Logger logger = Logger.getLogger(PayFactoryInstance.class);
    private static Map<String, IPayStrategy> registerServices = new ConcurrentHashMap<String, IPayStrategy>();

    private PayStrategyFactory() {
        init();
    }

    public static PayStrategyFactory getInstance() {
        return PayFactoryInstance.instance;
    }

    private static class PayFactoryInstance {
        private static PayStrategyFactory instance = new PayStrategyFactory();

    }

    private void init() {
        Set<Class<?>> classes = ClassScanner.scanPackage("com.bj.drj.design01.factory.impl");
        classes.stream().forEach(x -> registerService(x));
    }

    private void registerService(Class registerClass) {
        try {
            registerServices.put(registerClass.getName(), (IPayStrategy) registerClass.newInstance());
        } catch (Exception e) {
            logger.error(e);
        }
    }

    public IPayStrategy getPayService(String payCode) {
        return registerServices.get(PayEnum.getClassPath(payCode));
    }
}

支付方式枚举

/**
 * @ClassName PayEnum
 * @Description 支付方式枚举
 * @Author drj
 * @Date 2021/8/11 2:14 下午
 */
public enum PayEnum {

    ALI_PAY("ali", "com.bj.drj.design01.factory.impl.AliPay"),
    QQ_PAY("qq", "com.bj.drj.design01.factory.impl.QqPay"),
    WX_PAY("wx", "com.bj.drj.design01.factory.impl.WxPay");

    private String payCode;

    private String payClassPath;

    public String getPayCode() {
        return payCode;
    }

    public String getPayClassPath() {
        return payClassPath;
    }

    PayEnum(String payCode, String payClassPath) {
        this.payCode = payCode;
        this.payClassPath = payClassPath;
    }

    public static String getClassPath(String payCode) {
        for (PayEnum payEnum : values()) {
            if (Objects.equals(payEnum.getPayCode(), payCode)) {
                return payEnum.getPayClassPath();
            }
        }
        return null;
    }

}

支付实现类(aliPay)

这里只写模拟阿里支付宝实现类,其他类似

public class AliPay implements IPayStrategy<AliPayRequest> {
    /**
     * @param payBusiness
     * @return
     * @throws Exception
     */
    @Override
    public Result<AliPayResponse> pay(PayBusiness<AliPayRequest> payBusiness) throws Exception {
        AliPayRequest aliPayRequest = new AliPayRequest();
        aliPayRequest.setAli("阿里云");
        payBusiness.setBody(aliPayRequest);
        IPayStrategy.logger.info("Ali Pay 请求参数: " + JSON.toJSONString(payBusiness));
        Result<AliPayResponse> responseResult = new Result<>();
        responseResult.setResultCode(200);
        responseResult.setResultMsg("调用成功!");
        AliPayResponse aliPayResponse = new AliPayResponse();
        aliPayResponse.setAliPayResult("aliPay 接口调用成功 等待回调");
        responseResult.setResultData(aliPayResponse);
        return responseResult;
    }
}

服务调用

/**
 * @ClassName PayBusiness
 * @Description: TODO
 * @Author drj
 * @Date 2021/8/10
 * @Version V1.0
 **/
public class PayBusiness<T> {

    /**
     * 支付金額
     */
    private BigDecimal payAccount;

    /**
     * 支付方式
     */
    private String payName;

    /**
     * 支付方式code
     */
    private String payCode;

    /**
     * 不同支付方式业务参数
     */
    private T body;

    public BigDecimal getPayAccount() {
        return payAccount;
    }

    public void setPayAccount(BigDecimal payAccount) {
        this.payAccount = payAccount;
    }

    public String getPayName() {
        return payName;
    }

    public void setPayName(String payName) {
        this.payName = payName;
    }

    public T getBody() {
        return body;
    }

    public void setBody(T body) {
        this.body = body;
    }

    public String getPayCode() {
        return payCode;
    }

    public void setPayCode(String payCode) {
        this.payCode = payCode;
    }
}

public class PayService {



    public Result pay(PayBusiness payBusiness) throws Exception {
       ContextStrategy contextHandler = new ContextStrategy(PayStrategyFactory.getInstance().getPayService(payBusiness.getPayCode()));
       return contextHandler.payProcess(payBusiness);
    }
    
}

从上面服务调用可以发现我们只需要传入请求参数两行代码实现service 层的调用。后面我们假如有新需求增加其他支付方式,比如:qq、wx 只需要增加枚举和对应的实现类,即可 很容易得到扩展。
请求参数和返回参数分别都使用泛型接受可变对象,使得我们更加灵活。

测试

public class PayTest {

    @Inject
    private PayService payService;

    @Inject
    private PayDemo payDemo;

    @Before
    public void init() {
        CommonInjector.getInjector().injectMembers(this);
    }

    @Test
    public void testWxPay() throws Exception {
        PayBusiness payBusiness = new PayBusiness();
        payBusiness.setPayAccount(new BigDecimal(200));
        payBusiness.setPayCode("wx");
        payBusiness.setPayName("微信");
        Result pay = payService.pay(payBusiness);
        System.out.printf("支付接口返回参数:" + JSON.toJSONString(pay));
    }


    @Test
    public void testAliPay() throws Exception {
        PayBusiness payBusiness = new PayBusiness();
        payBusiness.setPayAccount(new BigDecimal(200));
        payBusiness.setPayCode("ali");
        payBusiness.setPayName("阿里");
        Result pay = payService.pay(payBusiness);
        System.out.printf("支付接口返回参数:" + JSON.toJSONString(pay));
    }


    @Test
    public void testPay() throws Exception {
        PayBusiness payBusiness = new PayBusiness();
        payBusiness.setPayAccount(new BigDecimal(200));
        payBusiness.setPayCode("qq");
        payBusiness.setPayName("qq 钱包");
        Result payQq = payService.pay(payBusiness);
        System.out.println("支付接口返回参数:" + JSON.toJSONString(payQq));
        payBusiness.setPayCode("wx");
        payBusiness.setPayName("wx 支付");
        Result<WxPayResponse> payWx = payService.pay(payBusiness);
        System.out.println("支付接口返回参数:" + JSON.toJSONString(payWx));
        payBusiness.setPayCode("ali");
        payBusiness.setPayName("ali 支付");
        Result<AliPayResponse> payAli = payService.pay(payBusiness);
        System.out.println("支付接口返回参数:" + JSON.toJSONString(payAli));
    }



九月 28, 2021 11:42:59 下午 com.bj.drj.design01.factory.impl.QqPay pay
信息: QPay 请求参数: {“body”:{“qq”:“qq”},“payAccount”:200,“payCode”:“qq”,“payName”:“qq 钱包”}
九月 28, 2021 11:42:59 下午 com.bj.drj.design01.factory.impl.QqPay pay
信息: 调用qq支付
支付接口返回参数:{“resultCode”:200,“resultData”:{“qqPayResult”:“qqPay 接口调用成功 等待回调”},“resultMsg”:“调用成功!”}
支付接口返回参数:{“resultCode”:200,“resultData”:{“wxPayResult”:“wx Pay 接口调用成功, 等待回调”},“resultMsg”:“调用成功!”}
九月 28, 2021 11:42:59 下午 com.bj.drj.design01.factory.impl.WxPay pay
支付接口返回参数:{“resultCode”:200,“resultData”:{“aliPayResult”:“aliPay 接口调用成功 等待回调”},“resultMsg”:“调用成功!”}
信息: Wx Pay 请求参数: {“body”:{“wx”:“微信”},“payAccount”:200,“payCode”:“wx”,“payName”:“wx 支付”}
九月 28, 2021 11:42:59 下午 com.bj.drj.design01.factory.impl.AliPay pay
信息: Ali Pay 请求参数: {“body”:{“ali”:“阿里云”},“payAccount”:200,“payCode”:“ali”,“payName”:“ali 支付”}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蜗牛乌龟一起走

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值