-
把设计模式用的炉火纯青是真的有利于我们阅读源码,现在我也经常在阅读源码的时候进行总结,来提高自己代码的逼格。
-
下边这个demo融合了策略模式,适配模式,模板模式,桥接模式,运用这几种模式设计了一个支付框架
架构图
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我还没来得及跑,大家跑不起来可以给我留言,,我来改