首页 > 其他 > 详细

设计模式——策略模式实战

时间:2020-04-23 12:54:46      阅读:96      评论:0      收藏:0      [点我收藏+]

策略模式实战:支付代码优化

原支付逻辑

/**
    * 微信公众号/小程序预下单
    * @param businessId 业务id-发起支付主键id,用来关联业务用
    * @param userId 用户id/学生id
    * @param spbillIp 微信支付手机ip
    * @param schoolId 学校id
    */
  public String unifiedorderJH(String businessId ,String userId,String spbillIp,String schoolId) throws Exception {
      if(StringUtils.isBlank(businessId)){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"业务id不能为空");
      }
      if(StringUtils.isBlank(userId)){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"角色id不能为空");
      }
      if(StringUtils.isBlank(schoolId)){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"学校id不能为空");
      }
      //获取学校配置
      SysSchoolConfigVO configVO = sysSchoolConfigService.getInfoById(schoolId);
      if(StringUtils.isBlank(configVO.getMiniAppid1())){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"小程序id为空,请查看学校是否已经配置信息");
      }
      String mchId=sysConfigService.getConfigValue(schoolId, SysConfigConfig.GF_MCHID);
      String instId=sysConfigService.getConfigValue(schoolId, SysConfigConfig.GF_INSTID);
      String publicKey=sysConfigService.getConfigValue(schoolId, SysConfigConfig.GF_PUK);
      String privateKey=sysConfigService.getConfigValue(schoolId, SysConfigConfig.GF_PVK);
      String judgeRes=payParamJudge(configVO,mchId,instId,publicKey,privateKey);
      if (judgeRes!=null){
          return judgeRes;
      }
      SysWxUserVO wxUser=new SysWxUserVO();
      wxUser.setUserId(userId);
      SysWxUser wxUserObj =sysWxUserService.getWxUser(wxUser);
      if(wxUserObj==null||StringUtils.isBlank(wxUserObj.getOpenId1())){
          return buildResult(SystemStatusEnum.NoData.getValue(),"用户不存在");
      }
      SmNoticePaymoneyVO noticePaymoney=new SmNoticePaymoneyVO();
      noticePaymoney.setStId(userId);
      noticePaymoney.setNoticeId(businessId);
      noticePaymoney=smNoticePaymoneyService.findSmNoticePaymoneyByStId(noticePaymoney);
      if(noticePaymoney==null){
          return buildResult(SystemStatusEnum.NoData.getValue(),"订单不存在");
      }
      if(noticePaymoney.getCost()==null){
          return buildResult(SystemStatusEnum.NoData.getValue(),"支付金额为空");
      }
      if(SmNoticePaymoneyEnum.DELIVERED.getStatus().equals(noticePaymoney.getStatus())){
          return buildResult(SystemStatusEnum.InvalidParams.getValue(),"该订单已缴费或作废,无法继续缴费");
      }
      SmNoticeVO notice=new SmNoticeVO();
      notice.setNoticeId(businessId);
      SmNoticeVO noticeObj = smNoticeService.getOneData(notice);
      if (noticeObj==null) {
          return buildResult(SystemStatusEnum.NoData.getValue(),"业务数据不存在");
      }
      String subject=noticeObj.getSubject();
      //1.校验数据
      if(noticePaymoney.getCost()==null){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"费用不能为空");
      }
      if(StringUtils.isBlank(wxUserObj.getOpenId1())){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"用户openid不能为空");
      }
      if(StringUtils.isBlank(subject)){
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"费用名称不能为空");
      }
      //元转分-判断金额是否小于等于0
      if(noticePaymoney.getCost().compareTo(BigDecimal.ZERO)<=0)
      {
          return buildResult(SystemStatusEnum.ReqParamNull.getValue(),"订单金额必须大于0");
      }
      StBaseInfoVO stObj=stBaseInfoService.getByStName(userId);
      //判断支付方式
      switch (configVO.getPayWay()){
          //聚合支付
          case 0:
              return payService.unifiedorderJH(configVO.getMiniAppid1(),mchId,businessId,BusinessTypeEnum.CLASS_ACTIVITY,userId,noticePaymoney.getCost().toString(),
                      wxUserObj.getOpenId1(),spbillIp,subject,schoolId,stObj.getClassName(),stObj.getName());
          //富友支付
          case 1:
              return fyPayService.wxPreCreate(instId,mchId,configVO.getMiniAppid1(),businessId,BusinessTypeEnum.CLASS_ACTIVITY,userId,noticePaymoney.getCost().toString(),
                      wxUserObj.getOpenId1(),spbillIp,subject,schoolId,"01_WXPAY_PBPM",publicKey,privateKey,stObj.getClassName(),stObj.getName());
              default:
                  return buildResult(SystemStatusEnum.InvalidParams.getValue(),"请检查学校是否配置了支付方式");
      }
  }

主要问题在判断支付方式上面,如果继续对接相应的支付,是否是要继续在相应的下单,退款,查询等接口都增加判断,会让这个代码越来越难维护。。。

//判断支付方式
      switch (configVO.getPayWay()){
          //聚合支付
          case 0:
              return payService.unifiedorderJH(configVO.getMiniAppid1(),mchId,businessId,BusinessTypeEnum.CLASS_ACTIVITY,userId,noticePaymoney.getCost().toString(),
                      wxUserObj.getOpenId1(),spbillIp,subject,schoolId,stObj.getClassName(),stObj.getName());
          //富友支付
          case 1:
              return fyPayService.wxPreCreate(instId,mchId,configVO.getMiniAppid1(),businessId,BusinessTypeEnum.CLASS_ACTIVITY,userId,noticePaymoney.getCost().toString(),
                      wxUserObj.getOpenId1(),spbillIp,subject,schoolId,"01_WXPAY_PBPM",publicKey,privateKey,stObj.getClassName(),stObj.getName());
              default:
                  return buildResult(SystemStatusEnum.InvalidParams.getValue(),"请检查学校是否配置了支付方式");
      }

违反代码六大设计原则之一:开闭原则,如何进行优化修改?

利用设计模式之一:策略模式进行修改

定义一个支付的接口,里面包含:下单,退款,交易查询,退款查询等无论接入哪个支付通道都要用到的方法。

步骤1:新增支付接口IPayServiceImp

public interface IPayServiceImp {
?
  //支付类型
  public String payType();
?
  /**
    * 下单
    * @return
    */
  public String unifiedorderJH(String businessId ,String userId,String spbillIp,String schoolId);
?
  /**
    * 退款
    * @return
    */
  public String refundJH(String userId,String tradeNo,String schoolId,String refundFee,String remark);
?
  /**
    * 交易查询
    * @return
    */
  public String findOrderJH(String tradeNo,String schoolId);
?
  /**
    * 退款查询
    * @return
    */
  public String findRefOrderJH(String tradeNo,String refundNo,String schoolId);
?
}

步骤2:分别新增富友支付和聚合支付实现类:FuyouPayService和JuhePayService

@Service
public class FuyouPayService implements IPayServiceImp{
  @Override
  public String payType() {
      return "fuyou";
  }
?
  @Override
  public String unifiedorderJH(String businessId, String userId, String spbillIp, String schoolId) {
      //TODO 编写逻辑
      return "成功调用富有支付下单方法";
  }
?
  @Override
  public String refundJH(String userId, String tradeNo, String schoolId, String refundFee, String remark) {
      return "成功调用富有支付退款方法";
  }
?
  @Override
  public String findOrderJH(String tradeNo, String schoolId) {
      return null;
  }
?
  @Override
  public String findRefOrderJH(String tradeNo, String refundNo, String schoolId) {
      return null;
  }
}
@Service
public class JuhePayService implements IPayServiceImp {
  @Override
  public String payType() {
      return "juhe";
  }
?
  @Override
  public String unifiedorderJH(String businessId, String userId, String spbillIp, String schoolId) {
      //TODO 编写逻辑
      return "成功调用聚合支付下单方法";
  }
?
  @Override
  public String refundJH(String userId, String tradeNo, String schoolId, String refundFee, String remark) {
      return "成功调用聚合支付退款方法";
  }
?
  @Override
  public String findOrderJH(String tradeNo, String schoolId) {
      return null;
  }
?
  @Override
  public String findRefOrderJH(String tradeNo, String refundNo, String schoolId) {
      return null;
  }
}

步骤3:实现支付调用,创建一个支付业务类ArcPayService,根据传输的支付类型自动匹配相应的支付接口,该方法利用了设计模式之一:策略模式。具体原理:利用spring的特性,在类初始化的时候,注入所有的支付list,然后以payType为key,把这个list存储在map中,每次接口调用,根据payType这个key,找到相应的支付实现类,完成支付功能的正确调用。

@Service
public class ArcPayService {
?
  /**
    * iPayServiceImpList用一个map存起来
  */
  HashMap<String,IPayServiceImp> iPayMap=new HashMap<>();
?
  /**
    * 初始化,注入所有的支付List
    */
  @Autowired
  public ArcPayService(List<IPayServiceImp> iPayServiceImpList){
      for (IPayServiceImp iPayServiceImp:iPayServiceImpList){
          iPayMap.put(iPayServiceImp.payType(),iPayServiceImp);
      }
  }
?
  /**
    * 下单
    * @param payType
    * @return
    */
  public String unifiedorderJH(String payType){
      IPayServiceImp iPayServiceImp=iPayMap.get(payType);
      if(iPayServiceImp==null){
          return "支付方式不存在";
      }
      return iPayServiceImp.unifiedorderJH("","","","");
  }
?
  /**
    * 退款
    * @param payType
    * @return
    */
  public String refundJH(String payType){
      IPayServiceImp iPayServiceImp=iPayMap.get(payType);
      if(iPayServiceImp==null){
          return "支付方式不存在";
      }
      return iPayServiceImp.refundJH("","","","","");
  }
   
}

步骤4:测试,新增测试类ArcPayServiceTest

@SpringBootTest
@RunWith(SpringRunner.class)
public class ArcPayServiceTest {
?
  @Autowired
  ArcPayService arcPayService;
?
  @Test
  public void unifiedorderJH() {
      String fuyou= arcPayService.unifiedorderJH("fuyou");
      System.out.println("富有:"+fuyou);
      String juhe= arcPayService.unifiedorderJH("juhe");
      System.out.println("聚合:"+juhe);
      String xx= arcPayService.unifiedorderJH("xxx");
      System.out.println("其他:"+xx);
?
  }
?
  @Test
  public void refundJH() {
  }
}

输出相应的结果如下:

富有:成功调用富有支付下单方法
聚合:成功调用聚合支付下单方法
其他:支付方式不存在

至此完成了这个代码的升级改造,后续继续增加支付对接,只要继续增加一个支付方式的实现类就可以了,完全不用修改原来的代码。

设计模式——策略模式实战

原文:https://www.cnblogs.com/shuideqing/p/12759771.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!