桥接模式介绍
桥接模式的作用是通过将抽象部分与实现部分分离,将多种可匹配的使用进行组合。其核心实现是在A类中含有B类接口,通过构造函数传递B类的实现,这个B类就是设计的桥。
这样的桥接模式存在于日常开发中的那些场景呢,包括JDBC多种驱动程序的实现,同品牌类型的台式机和笔记本电脑、业务实现中的多类接口同组过滤服务服务等。这些场景都比较适合用桥接模式实现,因为在一些组合中,如果每一个类都实现不同的服务,可能会出现笛卡尔积,而使用桥接模式就可以变得非常简单。
简单桥接模式使用
场景:多支付和多模式组合场景
在支付服务行业中,有微信、支付宝及一些其他支付服务,但是对于商家来说,并不能只接受某一种支付方式。如果商家只支持使用微信或支付宝付款,那么就会让顾客为难,商品销量也会受到影响。
这时就出现了第三方平台,它们把市面上的多种支付服务都集中到自己平台中,再把这些平台提供给店铺、超市等商家使用,同时支持人脸支付、指纹支付和密码支付等多种支付方式。
违背设计模式实现
没有什么事if…else解决不了的事情
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | package com.bestrookie.design;import java.math.BigDecimal;
 
 
 
 
 public class PayController {
 public Boolean dpPay(String uId, String tradeId, BigDecimal amount,int channelType,int modeType) {
 if (1 == channelType) {
 System.out.println("模拟微信渠道支付 uid: " + uId + " tradeId" + tradeId);
 if (modeType == 1) {
 System.out.println("密码支付");
 } else if (modeType == 2) {
 System.out.println("人脸支付");
 } else if (modeType == 3) {
 System.out.println("指纹支付");
 }
 } else if (2 == channelType) {
 System.out.println("模拟支付宝渠道支付 uid: " + uId + " tradeId" + tradeId);
 if (modeType == 1) {
 System.out.println("密码支付");
 } else if (modeType == 2) {
 System.out.println("人脸支付");
 } else if (modeType == 3) {
 System.out.println("指纹支付");
 }
 }
 return true;
 }
 }
 
 | 
逻辑简单明了,已经满足了不同支付类型和支付模式的组合,但是这样的代码在后面的维护以及扩展中都会变得非常复杂。
桥接模式重构代码
从上面的if…else实现方式来看,这时两种不同类型的相互组合。可以把支付类型和支付模式分离,通过抽象类依赖实现类的方式进行桥接。按照这种方式拆分后,支付方式与支付模式可以单独使用,当需要组合时,只需要把模式传递给各类支付方式。
桥接模式的关键是选择桥接点拆分,看能否找到这样类似的相互组合,如果没有就不用必须使用桥接模式。

- 左侧Pay是一个抽象类,下面是它的两种支付类型:微信支付和支付宝支付。
- 右侧IPayMode是一个接口,下面是它的三种支付模式:密码支付、人脸支付和指纹支付
- 支付类型 X 支付模式 = 相应的组合
支付类型桥接抽象类
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | package com.bestrookie.design.pay.channel;import com.bestrookie.design.pay.model.IPayModel;
 import java.math.BigDecimal;
 
 
 
 
 public abstract class Pay {
 protected IPayModel iPayModel;
 public Pay(IPayModel iPayModel){
 this.iPayModel = iPayModel;
 }
 public abstract String transfer(String uId, String tradeId, BigDecimal amount);
 }
 
 | 
如果没有接触过此类支付需求,可以终点关注IPayMode payMode,这部分是桥接模式的核心。
两种支付类型的实现
微信:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | package com.bestrookie.design.pay.channel;import com.bestrookie.design.pay.model.IPayModel;
 import java.math.BigDecimal;
 
 
 
 
 public class WxPay extends Pay{
 public WxPay(IPayModel iPayModel) {
 super(iPayModel);
 }
 @Override
 public String transfer(String uId, String tradeId, BigDecimal amount) {
 System.out.println("微信支付开始  uId:"+uId+" tradeId: "+tradeId);
 boolean security = iPayModel.security(uId);
 System.out.println("安全验证=========");
 if (!security){
 System.out.println("安全验证未通过============");
 return "0001";
 }
 System.out.println("安全验证通过===========");
 return "00000";
 }
 }
 
 | 
支付宝:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | package com.bestrookie.design.pay.channel;import com.bestrookie.design.pay.model.IPayModel;
 import java.math.BigDecimal;
 
 
 
 
 public class ZfbPay extends Pay{
 public ZfbPay(IPayModel iPayModel) {
 super(iPayModel);
 }
 
 @Override
 public String transfer(String uId, String tradeId, BigDecimal amount) {
 System.out.println("模拟支付宝支付 uId: "+uId+" readeId: "+tradeId);
 boolean security = iPayModel.security(uId);
 System.out.println("安全验证====================");
 if (!security){
 System.out.println("安全验证未通过================");
 return "0001";
 }
 System.out.println("安全验证通过===============");
 return "0000";
 }
 }
 
 
 | 
定义支付模式接口
| 12
 3
 4
 5
 6
 7
 8
 
 | package com.bestrookie.design.pay.model;
 
 
 
 public interface IPayModel {
 boolean security(String uId);
 }
 
 | 
三种支付模式风控
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | package com.bestrookie.design.pay.model;
 
 
 
 
 public class PayFaceMode implements IPayModel{
 public boolean security(String uId) {
 System.out.println("人脸支付=======");
 return true;
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | package com.bestrookie.design.pay.model;
 
 
 
 public class PayFingerprintMode implements IPayModel{
 public boolean security(String uId) {
 System.out.println("指纹支付======");
 return true;
 }
 }
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | package com.bestrookie.design.pay.model;
 
 
 
 public class PayCypher implements IPayModel{
 public boolean security(String uId) {
 System.out.println("密码支付=======");
 return true;
 }
 }
 
 | 
与上面的if…else实现方式相比,这里的调用方式变得整洁、干净和易用。玩不使用接口的用户不需要关心具体的实现,只需要选择使用即可。
总结
从桥接模式的实现形式来看,它满足了单一职责和开闭原则,让每一部分内容都很清晰,易于维护和扩展。但如果实现的高内聚的代码,则会很复杂。所以在选择重构代码时,需要考虑整体的设计。如果运用的设计模式不合理,也会让代码变得难以开发和维护。
任何一种设计模式的原则和使用都应该以符合场景为主,不能刻意使用。由于业务的复杂性,可能需要用到多种设计模式,才能将代码变得更加合理。