一、桥接模式原理

桥接模式最根本的思想:将抽象部分与实现部分进行分离。两个维度的部分原来是糅杂在一起,现在使用桥接模式将两部分进行分离。

1 举个例子

举个例子:

电商支付方式有以下6种:微信指纹支付、微信人脸支付、微信密码支付;支付宝指纹支付、支付宝人脸支付、支付宝密码支付

如果我们使用传统的方式编写代码:

if(mode=="微信"){
    if(method="人脸"){
        ....
    }
    if(method="指纹"){
        ....
    }
    if(method="密码"){
        ....
    }
}
if(mode=="支付宝"){
    if(method="人脸"){
        ....
    }
    if(method="指纹"){
        ....
    }
    if(method="密码"){
        ....
    }
}

我们很明显能发现问题,如果要再加一种支付类型比如“银行”,那me又会多很多很多ifelse;如果再增加一种支付方式,那么所有支付类型(微信、阿里、银行)都要增加一条ifelse。这样的代码即冗杂又不美观而且违背开闭原则,所以桥接模式登场。

使用桥接模式,就要找到两个维度,上面的例子非常容易找到。第一个维度就是“支付类型”,第二个维度就是“支付方式”。

再找到两个维度后,我们可以进行如下的操作:

  1. 第一个维度是不是都有“支付”的功能,那么我们将“支付”的功能提取出来放到抽象类Pay里面的transfer方法,其他WeixinPay、ZhiFuBaoPay去继承抽象类Pay并且重写transfer方法。
  2. 第二个维度都有“支付校验”功能,只是各自实现的方式不太一样,那么我们将“支付校验”的功能提取出来放到接口IPayMode里面,其他FacePayMode、FingerprintMode去实现IPayMode的支付方法security。
  3. 现在看,我们将两个维度完全分离开来,这两个维度毫不相干。但是我们要将他们组合起来,也就是说我在使用微信支付(维度一)的时候要选择一种校验方式(维度二),所以我们要将第二个维度的对象放在第一个维度中(组合),通过传参的方式选择校验方式。



支付宝技术架构图 支付宝vie架构_设计模式


2 桥接模式引入

那么接下来我们引出桥接模式的四个角色。

Abstraction:抽象化角色 ---- 对应 Pay

RefinedAbstraction:扩展抽象化角色 ---- 对应WeixinPay、ZhiFuBaoPay

Implementor:实现化角色 ---- 对应IPayMode

ConcreteImplementor:具体实现化角色 ---- 对应FacePayMode、FingerprintMode


支付宝技术架构图 支付宝vie架构_设计模式_02


二、代码

// 抽象化角色
/**
 * 支付抽象类
 */
public abstract class Pay {
    //桥接对象
    protected IPayMode payMode;

    public Pay(IPayMode payMode) {
        this.payMode = payMode;
    }

    //划账
    public abstract String transfer(String uid, String tradeId, BigDecimal amount);

}

//扩展抽象化角色
public class WeixinPay extends Pay{

    public WeixinPay(IPayMode payMode) {
        super(payMode);
    }

    @Override
    public String transfer(String uid, String tradeId, BigDecimal amount) {
        System.out.println("微信渠道支付划账开始......");
        boolean security = payMode.security(uid);

        if(!security){
            System.out.println("微信渠道失败");
            return "500";
        }else{
            System.out.println("微信渠道成功");
            return "200";
        }
    }
}
public class ZhiFuBaoPay extends Pay{

    public ZhiFuBaoPay(IPayMode payMode) {
        super(payMode);
    }

    @Override
    public String transfer(String uid, String tradeId, BigDecimal amount) {
        System.out.println("支付宝渠道支付划账开始......");
        boolean security = payMode.security(uid);

        if(!security){
            System.out.println("支付宝渠道失败");
            return "500";
        }else{
            System.out.println("支付宝渠道成功");
            return "200";
        }
    }
}

//实现化角色
public interface IPayMode {
    //安全校验功能:对各种支付模式进行风控校验操作
    boolean security(String uid);
}

//具体实现化角色
/**
 * 指纹支付
 */
public class PayFingerprintMode implements IPayMode {
    @Override
    public boolean security(String uid) {
        System.out.println("指纹支付,风控校验--->指纹信息");
        return true;
    }
}
/**
 * 刷脸支付
 */
public class PayFaceMode implements IPayMode{
    @Override
    public boolean security(String uid) {
        System.out.println("人脸支付,风空校验--->脸部识别");
        return true;
    }
}
/**
 * 密码支付
 */
public class PayCyber implements IPayMode{
    @Override
    public boolean security(String uid) {
        System.out.println("密码支付,风控校验--->环境安全");
        return true;
    }
}

//test
public class Test {
    public static void main(String[] args) {
        Pay pay = new WeixinPay(new PayFaceMode());
        pay.transfer("1","1",new BigDecimal(100));
    }
}

三、优缺点

桥接模式的优点:

  1. 分离抽象接口及其实现部分.桥接模式使用"对象间的关联关系"解耦了抽象和实现之间固有的绑定关系,使得抽象和实现可以沿着各自的维度来变化。
  2. 在很多情况下,桥接模式可以取代多层继承方案.多层继承方案违背了单一职责原则,复用性差,类的个数多.桥接模式很好的解决了这些问题。
  3. 桥接模式提高了系统的扩展性,在两个变化维度中任意扩展一个维度都不需要修改原有系统,符合开闭原则。

桥接模式的缺点:

  1. 桥接模式的使用会增加系统的理解和设计难度,由于关联关系建立在抽象层,要求开发者一开始就要对抽象层进行设计和编程
  2. 桥接模式要求正确识别出系统中的两个独立变化的维度,因此具有一定的局限性,并且如果正确的进行维度的划分,也需要相当丰富的经验.