JAVA【设计模式】桥接模式
一、定义
桥接模式:将一个大类或者一系列相关的类拆分为抽象和实现两个独立的层级结构,从而在开发的时候独立使用
主要作⽤就是通过将抽象部分
与实现部分
分离,把多种可匹配
的使⽤进⾏组合
。说⽩了核⼼实现也就是在A类
中含有B类
接口,通过构造函数
传递B类
的实现,这个B类
就是设计的桥
。
在⼀些组合中如果有如果每⼀个类都实现不同的服务
可能会出现笛卡尔积
,⽽使⽤桥接模式就可以⾮常简单。
二、示例:
模拟场景:
1、例如:假如你有一个几何 形状Shape类, 从它能扩展出两个子类: 圆形Circle和 方形Square 。 你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为 红色Red和 蓝色Blue的形状子类。 但是, 由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合,例如蓝色圆形BlueCircle和 红色方形RedSquare 。
在层次结构中新增形状和颜色将导致代码复杂程度指数增长。 例如添加三角形状, 你需要新增两个子类, 也就是每种颜色一个; 此后新增一种新颜色需要新增三个子类, 即每种形状一个。 如此以往, 情况会越来越糟糕。
2、例如:随着市场的竞争在⽀付服务⾏业出现了微信和⽀付宝还包括⼀些其他⽀付服务,同时⽀持⼈脸、扫描、密码多种⽅式
模拟⼀个这样的第三⽅平台来承接各个⽀付能⼒,同时使⽤⾃家的⼈脸让⽤户⽀付起来更加容易。那么这⾥就出现了多⽀付与多模式的融合使⽤,如果给每⼀个⽀付都实现⼀次不同
的模式,即使是继承类也需要开发好多。⽽且随着后⾯接⼊了更多的⽀付服务或者⽀付⽅式,就会呈爆炸似
的扩展
传统编码方式(关于支付的)
一旦扩充新的支付平台或支付方式,需要多次if else的代码判断,扩充修改代码:PayController
package com.qf.design.structure.bridgeconnect.tradition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
public class PayController {
private Logger logger = LoggerFactory.getLogger(PayController.class);
public boolean doPay(String uId, String tradeId, BigDecimal amount, int channelType, int modeType) {
// 微信支付
if (1 == channelType) {
logger.info("模拟微信渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
if (1 == modeType) {
logger.info("密码支付,风控校验环境安全");
} else if (2 == modeType) {
logger.info("人脸支付,风控校验脸部识别");
} else if (3 == modeType) {
logger.info("指纹支付,风控校验指纹信息");
}
}
// 支付宝支付
else if (2 == channelType) {
logger.info("模拟支付宝渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
if (1 == modeType) {
logger.info("密码支付,风控校验环境安全");
} else if (2 == modeType) {
logger.info("人脸支付,风控校验脸部识别");
} else if (3 == modeType) {
logger.info("指纹支付,风控校验指纹信息");
}
}
return true;
}
}
测试:ApiTest
package com.qf.design.structure.bridgeconnect.tradition;
import java.math.BigDecimal;
public class ApiTest {
public static void main(String[] args) {
PayController pay = new PayController();
System.out.println("\r\n模拟测试场景;微信支付、人脸方式。");
pay.doPay("weixin_1092033111", "100000109893", new BigDecimal(100), 1, 2);
System.out.println("\r\n模拟测试场景;支付宝支付、指纹方式。");
pay.doPay("jlu19dlxo111","100000109894",new BigDecimal(100), 2, 3);
}
}
桥接模式(关于支付的)
桥接点,抽象接口,不同的支付方式实现此接口:IPayMode
package com.qf.design.structure.bridgeconnect.design.pay;
public interface IPayMode {
boolean security(String uid);
}
人脸支付:FacePayMode
package com.qf.design.structure.bridgeconnect.design.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FacePayMode implements IPayMode{
protected Logger logger = LoggerFactory.getLogger(FacePayMode.class);
@Override
public boolean security(String uid) {
logger.info("人脸支付,风控校验脸部识别");
return true;
}
}
指纹支付:FingerPayMode
package com.qf.design.structure.bridgeconnect.design.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FingerPayMode implements IPayMode{
protected Logger logger = LoggerFactory.getLogger(FacePayMode.class);
@Override
public boolean security(String uid) {
logger.info("指纹支付,风控校验指纹识别");
return true;
}
}
密码支付:PayCypher
package com.qf.design.structure.bridgeconnect.design.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PayCypher implements IPayMode{
protected Logger logger = LoggerFactory.getLogger(FacePayMode.class);
@Override
public boolean security(String uid) {
logger.info("密码支付,风控校验支付环境");
return true;
}
}
支付平台抽象类,可以传递不同的支付方式的实现类:Pay
package com.qf.design.structure.bridgeconnect.design.pay;
import java.math.BigDecimal;
public abstract class Pay {
protected IPayMode payMode;
public Pay(IPayMode payMode){
this.payMode=payMode;
}
public abstract String transfer(String uId, String tradeId, BigDecimal amount);
}
微信支付:WeiXinPay
package com.qf.design.structure.bridgeconnect.design.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
public class WeiXinPay extends Pay{
protected Logger logger = LoggerFactory.getLogger(FacePayMode.class);
public WeiXinPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
logger.info("模拟微信渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
boolean security = payMode.security(uId);
logger.info("模拟微信渠道支付风控校验。uId:{} tradeId:{} security:{}", uId, tradeId, security);
if (!security) {
logger.info("模拟微信渠道支付划账拦截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0001";
}
logger.info("模拟微信渠道支付划账成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0000";
}
}
支付宝支付:AliPay
package com.qf.design.structure.bridgeconnect.design.pay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.math.BigDecimal;
public class AliPay extends Pay{
protected Logger logger = LoggerFactory.getLogger(FacePayMode.class);
public AliPay(IPayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
logger.info("模拟支付宝渠道支付划账开始。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
boolean security = payMode.security(uId);
logger.info("模拟支付宝渠道支付风控校验。uId:{} tradeId:{} security:{}", uId, tradeId, security);
if (!security) {
logger.info("模拟支付宝渠道支付划账拦截。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0001";
}
logger.info("模拟支付宝渠道支付划账成功。uId:{} tradeId:{} amount:{}", uId, tradeId, amount);
return "0000";
}
}
测试:ApiTest
package com.qf.design.structure.bridgeconnect.design.pay;
import java.math.BigDecimal;
public class ApiTest {
public static void main(String[] args) {
System.out.println("\r\n模拟测试场景;微信支付、人脸方式。");
Pay wxPay=new WeiXinPay(new FacePayMode());
wxPay.transfer("weixin_1092033111", "100000109893", new BigDecimal(100));
System.out.println("\r\n模拟测试场景;支付宝支付、指纹方式。");
Pay zfbPay=new AliPay(new FingerPayMode());
zfbPay.transfer("jlu19dlxo111","100000109894",new BigDecimal(100));
}
}
桥接模式(几何形状)
桥接点,抽象接口,不同的颜色实现此接口:Color
package com.qf.design.structure.bridgeconnect.design.shape;
public interface Color {
void decorate();
}
红色:RedColor
package com.qf.design.structure.bridgeconnect.design.shape;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RedColor implements Color{
private Logger logger= LoggerFactory.getLogger(Logger.class);
@Override
public void decorate() {
logger.info("装修设计红色");
}
}
白色:WhiteColor
package com.qf.design.structure.bridgeconnect.design.shape;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class WhiteColor implements Color{
private Logger logger= LoggerFactory.getLogger(Logger.class);
@Override
public void decorate() {
logger.info("装修设计白色");
}
}
抽象类:Shape
package com.qf.design.structure.bridgeconnect.design.shape;
public abstract class Shape {
private Color color;
public abstract void decorateShape(Color color);
}
长方形:Rectangle
package com.qf.design.structure.bridgeconnect.design.shape;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Rectangle extends Shape{
private Logger logger= LoggerFactory.getLogger(Logger.class);
@Override
public void decorateShape(Color color) {
color.decorate();
logger.info("长方形的形状");
}
}
圆形:Circle
package com.qf.design.structure.bridgeconnect.design.shape;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Circle extends Shape{
private Logger logger= LoggerFactory.getLogger(Logger.class);
@Override
public void decorateShape(Color color) {
color.decorate();
logger.info("圆的形状");
}
}
测试:ApiTest
package com.qf.design.structure.bridgeconnect.design.shape;
public class ApiTest {
public static void main(String[] args) {
Shape shape=new Rectangle();
shape.decorateShape(new RedColor());
Shape circle=new Circle();
circle.decorateShape(new RedColor());
}
}
UML关系图
总结:
通过模拟微信与⽀付宝两个⽀付渠道在不同的⽀付模式下, 刷脸 、 指纹 、 密码 ,的组合从⽽体现了桥接模式的在这类场景中的合理运⽤。简化了代码的开发,给后续的需求迭代增加了很好的扩展性。
从桥接模式的实现形式来看满⾜了单⼀职责和开闭原则,让每⼀部分内容都很清晰易于维护和拓展,但如果我们是实现的⾼内聚的代码,那么就会很复杂。所以在选择᯿构代码的时候,需要考虑好整体的设计,否则选不到合理的设计模式,将会让代码变得难以开发