设计模式的综合运用

75 阅读3分钟
  1. 把设计模式用的炉火纯青是真的有利于我们阅读源码,现在我也经常在阅读源码的时候进行总结,来提高自己代码的逼格。

  2. 下边这个demo融合了策略模式,适配模式,模板模式,桥接模式,运用这几种模式设计了一个支付框架

架构图

image.png

demo

// 支付方式
public interface IPayMode {
    // 校验是否通过
    boolean security(UserInfo info);
      // 检查是否支持当前支付方式
    boolean support(String payWay);


    public String getType();
}


@Slf4j
@Component
public class PayCypher implements IPayMode {
    public boolean security(UserInfo uId) {
        log.info("密码支付,风控校验环境安全");
        return true;
    }

    @Override
    public boolean support(String payWay) {
        if ("password".equals(payWay)){
            return true;
        }
        return false;
    }

    @Override
    public String getType() {
        return "password";
    }
}




@Slf4j
@Component
public class PayFaceMode implements IPayMode {
    public boolean security(UserInfo info) {
        log.info("人脸支付,风控校验脸部识别");
        return true;
    }


    @Override
    public boolean support(String payWay) {
        if ("Face".equals(payWay)){
            return true;
        }
        return false;
    }

    @Override
    public String getType() {
        return "Face";
    }

}




@Slf4j
@Component
public class PayFingerprintMode implements IPayMode{
    public boolean security(UserInfo info) {
        log.info("指纹支付,风控校验指纹信息");
        return true;
    }


    @Override
    public boolean support(String payWay) {
        if ("Fingerprint".equals(payWay)){
            return true;
        }
        return false;
    }

    @Override
    public String getType() {
        return "Fingerprint";
    }


}


public interface Target {
    IPayMode request(UserInfo info);
}


/**
 * 适配器
 * 通过这个适配器找到是哪种支付验证方式
 */
@Slf4j
@Component
public class PayAdapter implements Target, InitializingBean {


    private Map<String, IPayMode> payModeMap;

    @Autowired
    private ApplicationContext ac;

    @Override
    public IPayMode request(UserInfo info) {
        log.info("模拟支付验证开始info{}",info);
        Target mode = null;
        String payMode = info.getPayMode();
        IPayMode PayModeBean = payModeMap.get(payMode);
        if (Objects.isNull(PayModeBean)){
            throw new RuntimeException("未找到支付验证途径");
        }
        return PayModeBean;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        try {
            ac.getBeansOfType(IPayMode.class).values().forEach(value -> {
                payModeMap.put(value.getType(), value);
            });
        }catch (Exception e){
            System.out.println("init  error" + e);
        }

    }
}



@Slf4j
@Component
public abstract class AbstractedPay implements InitializingBean {

    @Autowired
    Target adapter;


    @Autowired
    private ApplicationContext ac;


    private Map<String, AbstractedPay > payMap;


    // 支付方式前置工作
    public void template(UserInfo info){
        // 第一步:支付方式(微信、支付宝)方式的选择
        String payWay = info.getPayWay();
        AbstractedPay payBean = payMap.get(payWay);
        if (Objects.isNull(payBean)){
            System.out.println("can not get payBean");
            return;
        }

        // 第二步:找到支付的确认方式
        IPayMode payMode = findPayMode(info);
        // 第三步:支付安全校验
        boolean security = payMode.security(info);
        if (!security){
            throw new RuntimeException("支付方式安全校验失败");
        }
        // 第四步: 进行扣款转账
        Boolean transfer = transfer(info);
        if (!transfer) {
            throw new RuntimeException("交易失败");
        }

    }

    public IPayMode findPayMode(UserInfo info){
        IPayMode payMode = adapter.request(info);
        return payMode;
    }

    // 支付方式(微信、支付宝)方式的选择
    public abstract boolean support(String payWay);

    // 支付过程
    public abstract Boolean transfer(UserInfo info);


    public abstract String getType();

    @Override
    public void afterPropertiesSet() throws Exception {
        ac.getBeansOfType(AbstractedPay.class).values().forEach(value -> {
            payMap.put(this.getType(), value);
        });

    }

}



@Slf4j
@Component
public class WxPay extends AbstractedPay {

    @Override
    public boolean support(String payWay) {
        return "wx".equals(payWay);
    }

    @Transactional
    public Boolean transfer(UserInfo info) {
        String tradeId = info.getTradeId();
        BigDecimal total = info.getTotal();
        // 调用交易方式付款
        System.out.println("交易单:"+tradeId+" 费用是:"+total+" 支付方式是:"+info.getPayWay()+" 完成付款");
        return true;
    }

    @Override
    public String getType() {
        return "wx";
    }


}


@Slf4j
@Component
public class ZfbPay extends AbstractedPay {

    @Override
    public boolean support(String payWay) {
        return "zfb".equals(payWay);
    }

    @Transactional
    public Boolean transfer(UserInfo info) {
        String tradeId = info.getTradeId();
        BigDecimal total = info.getTotal();
        // 调用交易方式付款
        System.out.println("交易单:"+tradeId+" 费用是:"+total+" 支付方式是:"+info.getPayWay()+" 完成付款");
        return true;
    }

    @Override
    public String getType() {
        return "zfb";
    }
}

@Data
public class UserInfo {
    private String idCard;
    private String password;
    private String iphoneNum;
    private String payWay;
    private String payMode;
    private String tradeId;
    private BigDecimal total;
}

测试demo

@SpringBootTest
class PayWayApplicationTests {

    @Autowired
    List<AbstractedPay> abstractedPays;

    @Test
    void contextLoads() {
        UserInfo userInfo = new UserInfo();
        userInfo.setIdCard("1411xxx");
        userInfo.setIphoneNum("13250967872");
        userInfo.setPassword("123");
        userInfo.setPayWay("zfb");
        userInfo.setTradeId("123456");
        userInfo.setPayMode("Face");
        userInfo.setTotal(new BigDecimal("100"));

        for (AbstractedPay pay: abstractedPays) {
            if (pay.support(userInfo.getPayWay())){
                pay.template(userInfo);
                break;
            }
        }
    }
}

写在最后

    感谢up主是秦同学呀提供的思路和素材,一起学习和进步
    
    测试demo我还没来得及跑,大家跑不起来可以给我留言,,我来改