桥接模式
概述
桥接模式是将抽象部分与它的实现部分分离,使它们都可以独立地变化。它是一种对象结构型模式,又称为柄体(Handle and Body)模式或接口(interface)模式。
示例程序
现如今电子支付非常流行,熟悉的有微信支付,支付宝支付等,那么就有程序应运而生,综合多种支付接口,不论微信支付还是支付宝还是其他支付,通过他的接口可以分发到不同的策略中。除了支付通道之外,还有多种支付方式,比如刷脸支付、扫码支付、密码支付。支付通道和支付方式是完全互不关联的,我们通过桥接模式将两者关联起来。
普通模式实现
普通模式是看起来最易懂的模式,用if-else判断即可,但是对于后续添加其他支付接口来说,就要修改源代码,不符合开闭原则。
@Slf4j
@Service
public class PayService {
public boolean doPay(String uId, String tradeId, BigDecimal amount, int channelType, int modeType){
//微信支付
if (channelType == 1){
log.info("模拟微信渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
if (modeType == 1){
//人脸支付
log.info("人脸支付,风控校验脸部识别");
}else if (modeType == 2){
//指纹支付
log.info("指纹支付,风控校验指纹信息");
}else if (modeType == 3){
//密码支付
log.info("密码支付,风控校验环境安全");
}
}
//支付宝支付
else if (channelType == 2){
log.info("模拟支付宝渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
if (modeType == 1){
//人脸支付
log.info("人脸支付,风控校验脸部识别");
}else if (modeType == 2){
//指纹支付
log.info("指纹支付,风控校验指纹信息");
}else if (modeType == 3){
//密码支付
log.info("密码支付,风控校验环境安全");
}
}
return true;
}
}
桥接模式实现
我们将两种不同类型的属性分为通过IPayMode接口来进行桥接
IPayMode
public interface IPayMode {
boolean security(String uid);
}
Pay
public abstract class Pay {
protected IPayMode payMode;
public Pay(IPayMode payMode) {
this.payMode = payMode;
}
public abstract String transfer(String uId, String tradeId, BigDecimal amount);
}
WxPay
@Slf4j
public class WxPay extends Pay{
public WxPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
log.info("模拟微信渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
boolean security = payMode.security(uId);
log.info("模拟微信渠道支付风控校验。uId:{} tradeId:{} security:{}", uId, tradeId, security);
if (!security) {
log.info("模拟微信渠道支付划账拦截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0001";
}
log.info("模拟微信渠道支付划账成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0000";
}
}
ZfbPay
@Slf4j
public class ZfbPay extends Pay{
public ZfbPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
log.info("模拟支付宝渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
boolean security = payMode.security(uId);
log.info("模拟支付宝渠道支付风控校验。uId:{} tradeId:{} security:{}", uId, tradeId, security);
if (!security) {
log.info("模拟支付宝渠道支付划账拦截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0001";
}
log.info("模拟支付宝渠道支付划账成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0000";
}
}
PayFaceMode
@Slf4j
public class PayFaceMode implements IPayMode{
@Override
public boolean security(String uid) {
log.info("人脸支付,风控校验脸部识别");
return true;
}
}
PayPwdMode
@Slf4j
public class PayPwdMode implements IPayMode{
@Override
public boolean security(String uid) {
log.info("密码支付,风控校验环境安全");
return true;
}
}
PayFingerprintMode
@Slf4j
public class PayFingerprintMode implements IPayMode{
@Override
public boolean security(String uid) {
log.info("指纹支付,风控校验指纹信息");
return true;
}
}
测试
@SpringBootTest
class Practice1001ApplicationTests {
@Test
void contextLoads() {
Pay wxPay = new WxPay(new PayFaceMode());
wxPay.transfer("10001","wx10001",new BigDecimal(1000));
Pay zfbPay = new ZfbPay(new PayFingerprintMode());
zfbPay.transfer("10002","zfb10002",new BigDecimal(1000));
}
}