桥接模式简单来说就是将抽象部分与它的实现部分分离,使它们都可以独立地变化。
一些组合中如果有如果每一个类都实现不同的服务可能会出现笛卡尔积,而使用桥接模式就可以非常简单的将抽象化与实现化脱耦,使得二者可以独立地变化。怎么理解呢,假设我们有一个支付订单的任务,我们可以通过支付宝和微信支付来实现支付,支付宝和微信支付又分别对应了人脸识别和指纹识别。支付方式和验证方式可以两两对应,这时候的选择就产生了笛卡尔积:
支付宝+人脸,支付宝+指纹,微信+人脸,微信+指纹。
随着支付方式和验证方式的增加,我们产生的笛卡尔积就越发的多,如果我们使用强关联的方法去构建代码,会造成大量的死代码,增加工作量。
对于这种问题,一个解决方案就是使用桥接模式。我们把支付宝和微信抽象成为支付类,人脸和指纹抽象成为验证方式,中间使用一个桥来把它们进行连接,这就是桥接模式的基本实现了。也就是当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时,我们使用桥接模式会更加的方便扩展。
=========================================================================
我们模拟一下上面的支付例子:
我们使用桥接,就会考虑桥两边的部分,我们可以抽象出两个大类,一个是支付的方式,一个是验证的方式。然后我们把这两个部分衔接起来。我们每一个支付方式都需要验证,所以我们把验证模式抽象成为一个接口:
验证模式的接口(桥接接口):
package BridgePattern;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName PayMode.java
* @Description 验证模式接口
* @createTime 2022年03月07日 09:04:00
*/
public interface PayMode {
/**
* 权限验证
* @param uid 用户id
* @return 是否验证成功
*/
boolean security(String uid);
}
然后把支付方式提取成一个抽象类:
package BridgePattern;
import java.math.BigDecimal;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Payment.java
* @Description 支付方式抽象类
* @createTime 2022年03月07日 09:01:00
*/
public abstract class Payment {
/**
* 桥接接口
*/
protected PayMode payMode;
public Payment(PayMode payMode){
this.payMode = payMode;
}
/**
* 转账接口
* @param uId 用户ID
* @param tradeId 交易ID
* @param amount 支付总额
* @return 成功信息
*/
public abstract String transfer(String uId, String tradeId, BigDecimal amount);
}
支付方式的具体实现:
支付宝:
package BridgePattern.payment;
import BridgePattern.PayMode;
import BridgePattern.Payment;
import java.math.BigDecimal;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName Alipay.java
* @Description 支付宝
* @createTime 2022年03月07日 09:12:00
*/
public class Alipay extends Payment {
public Alipay(PayMode payMode) {
super(payMode);
}
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
//权限验证
boolean security = payMode.security(uId);
System.out.println("支付宝转账:");
System.out.println("确认对方账号:"+tradeId);
if (!security){
return "权限校验失败";
}else {
return "支付宝转账成功,支付金额:"+amount+"元";
}
}
}
微信支付 :
package BridgePattern.payment;
import BridgePattern.PayMode;
import BridgePattern.Payment;
import java.math.BigDecimal;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName WechatPay.java
* @Description 微信支付类
* @createTime 2022年03月07日 09:08:00
*/
public class WechatPay extends Payment {
@Override
public String transfer(String uId, String tradeId, BigDecimal amount) {
//权限验证
boolean security = payMode.security(uId);
System.out.println("微信转账:");
System.out.println("确认对方账号:"+tradeId);
if (!security){
return "权限校验失败";
}else {
return "微信转账成功,支付金额:"+amount+"元";
}
}
public WechatPay(PayMode payMode){
super(payMode);
}
}
验证接口的具体实现:
面部识别验证 :
package BridgePattern.PayModes;
import BridgePattern.PayMode;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName FacialRecognition.java
* @Description 面部识别
* @createTime 2022年03月07日 09:16:00
*/
public class FacialRecognition implements PayMode {
@Override
public boolean security(String uid) {
System.out.println("面部识别调用");
return "00001".equals(uid);
}
}
指纹识别验证 :
package BridgePattern.PayModes;
import BridgePattern.PayMode;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName fingerPrintIdentification.java
* @Description 指纹识别
* @createTime 2022年03月07日 09:20:00
*/
public class FingerPrintIdentification implements PayMode {
@Override
public boolean security(String uid) {
System.out.println("指纹识别调用");
return "00001".equals(uid);
}
}
测试一下:
package BridgePattern;
import BridgePattern.PayModes.FingerPrintIdentification;
import BridgePattern.payment.WechatPay;
import java.math.BigDecimal;
/**
* @author Zeyu Wan
* @version 1.0.0
* @ClassName BridgePatternTest.java
* @Description 桥接模式测试类
* @createTime 2022年03月07日 09:22:00
*/
public class BridgePatternTest {
public static void main(String[] args) {
Payment pay = new WechatPay(new FingerPrintIdentification());
System.out.println(pay.transfer("00001","12345",new BigDecimal(99999)));
}
}
可以看到,用户在使用支付接口的时候,不需要去关注内部的实现,只需要关注于使用什么方式支 付以及使用什么方式进行支付验证。并且接口还具有良好的扩展性,比如添加支付方式以及添加验证方式,都可以通过简单的继承和实现来添加进我们的方法中,然后被用户所调用。
优点:
- 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。
- 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。
缺点:
- 桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。