Java设计模式再相识 (八)——桥接模式

要想将两个目的地进行连接,你需要一座桥梁。在软件开发中,我们可能会遇到需要将两种维度的对象进行整合,让其能够运行在一个系统中。例如输出不同颜色和字体的日志,如果使用传统的继承方式,我们要写很多的子类才能实现。通过桥接模式,我们就可以很好地解决这个问题。

桥接模式

桥接模式:即Bridge,它可以将抽象与实现分离,让这些组合可以自由地独立变化,从而降低抽象和实现之间的耦合度。桥接模式适用于类的层级结构复杂的场景中,常与适配器进行组合使用,在两个不同对象之间添加适配器以进行不同对象的正确桥接。光看概念可能有些抽象,下文我们将会通过具体示例进行讲解。

桥接模式的结构

  • 抽象化(Abstraction):抽象类的定义,它将使用“实现者(Implementor)”中的方法定义基本的功能。抽象化类中保存了一个实现者(Implementor)的实例。
  • 扩展抽象化(RefinedAbstraction):在抽象化类的基础上增加了新的功能,它是抽象化角色的子类,并实现父类中的业务方法。
  • 实现者(Implementor):实现者定义了用于实现Abstraction的接口方法,以供扩展抽象化类进行调用。
  • 具体实现者(ConcreteImplementor):该类负责实现Implementor中定义的接口。

实际应用场景

  • JDBC驱动:JDBC中巧妙使用了桥接模式来进行多种数据库的适配。在修改数据库时,用户只需要简单地修改配置文件,然后就可以使用与原来数据库相同的API,无需伤筋动骨地对整个项目进行修改适配。
  • 指纹/人脸支付场景:在我们使用微信,支付宝进行支付时,会有多种鉴权方法,例如支付密码,指纹,人脸支付。这时就适合使用桥接模式进行逻辑的编写。

示例

本文将以支付场景,详解桥接模式的应用。

我们购买商品的最后一步就是支付。电商平台通常会让你选择支付方式,这里以微信和支付宝为例。

假设某电商平台的支付方式为微信,支付宝支付。鉴权方式有支付密码,指纹,人脸支付,让用户自行选择。

如果我们使用传统方式进行开发,我们会想到这几种组合:微信->密码,微信->人脸,支付宝->密码…

这会导致我们使用大量的if else语句来判断用户的行为,代码将杂乱无章。本例我们来使用桥接模式解决这个需求。

首先我们创建支付的抽象鉴权类,也就是结构中的实现者。

IPaymentAuthorization.java

package com.yeliheng.bridge;

/**
 * 鉴权方式
 */
public interface IPaymentAuthorization {
    boolean authorization();
}

实现者中提供了一个鉴权接口authorization(),方便后面三种鉴权模式的接入。

接着,定义一个抽象化类

PayAbstraction.java

package com.yeliheng.bridge;

/**
 * 抽象化类
 */
public abstract class PayAbstraction {

    protected IPaymentAuthorization paymentAuth;

    public PayAbstraction(IPaymentAuthorization paymentAuth) {
        this.paymentAuth = paymentAuth;
    }

    /**
     * 支付
     * @param payer 转账者
     * @param payee 收款者
     */
    public abstract void pay(String payer,String payee,Long amount);

}

抽象化类中使用构造函数的方式注入IPaymentAuthorization接口,并定义了一个抽象方法pay(),用于处理转账逻辑。

接着我们分别创建微信和支付宝两个平台的支付类,实现抽象化类中的抽象方法。

WechatPay.java

package com.yeliheng.bridge;

/**
 * 扩展抽象化
 */
public class WechatPay extends PayAbstraction{

    public WechatPay(IPaymentAuthorization paymentAuth) {
        super(paymentAuth);
    }

    /**
     * 支付
     *
     * @param payer 转账者
     * @param payee 收款者
     */
    @Override
    public void pay(String payer, String payee, Long amount) {
        System.out.println("[订单创建] 转账人: " + payer + " 收款者: " + payee + " 转账金额: " + amount);
        System.out.println("[系统] 开始校验身份...");
        boolean auth = paymentAuth.authorization();
        if(auth) {
            System.out.println("[信息] 微信支付成功!转账人: " + payer + " 收款者: " + payee + " 转账金额: " + amount);
        }
    }
}

Alipay.java

package com.yeliheng.bridge;

/**
 * 扩展抽象化
 */
public class Alipay extends PayAbstraction{

    public Alipay(IPaymentAuthorization paymentAuth) {
        super(paymentAuth);
    }

    /**
     * 支付
     *
     * @param payer 转账者
     * @param payee 收款者
     */
    @Override
    public void pay(String payer, String payee, Long amount) {
        System.out.println("[订单创建] 转账人: " + payer + " 收款者: " + payee + " 转账金额: " + amount);
        System.out.println("[系统] 开始校验身份...");
        boolean auth = paymentAuth.authorization();
        if(auth) {
            System.out.println("[信息] 支付宝支付成功!转账人: " + payer + " 收款者: " + payee + " 转账金额: " + amount);
        }
    }
}

最后,我们需要创建三种鉴权方式的类,来对实现者进行实现。

密码验证:PasswordAuthorization.java

package com.yeliheng.bridge;

public class PasswordAuthorization implements IPaymentAuthorization{

    @Override
    public boolean authorization() {
        //TODO: 具体的密码验证逻辑...
        System.out.println("[系统] 支付密码验证通过!");
        return true;
    }
}

指纹验证:FingerprintAuthorization.java

package com.yeliheng.bridge;

public class FingerprintAuthorization implements IPaymentAuthorization{
    @Override
    public boolean authorization() {
        //TODO: 具体的指纹验证逻辑...
        System.out.println("[系统] 指纹验证通过!");
        return true;
    }
}

人脸验证:FaceAuthorization.java

package com.yeliheng.bridge;

public class FaceAuthorization implements IPaymentAuthorization{
    @Override
    public boolean authorization() {
        //TODO: 具体的人脸验证逻辑...
        System.out.println("[系统] 人脸验证通过!");
        return true;
    }
}

为了演示效果,我们直接默认验证通过,并返回true。

处理完这些逻辑后,我们可以开始使用桥接模式实现的支付了。

Main.java

package com.yeliheng.bridge;

public class Main {
    public static void main(String[] args) {
        //微信人脸支付
        System.out.println("用户选择使用微信人脸支付,开始模拟。");
        PayAbstraction wechatPay = new WechatPay(new FaceAuthorization());
        wechatPay.pay("Yeliheng","Gnehiley",100000L);

        //支付宝指纹支付
        System.out.println("\n用户选择使用支付宝指纹支付,开始模拟。");
        PayAbstraction alipay = new Alipay(new FingerprintAuthorization());
        alipay.pay("Yeliheng","Gnehiley",100000L);
    }
}

在main函数中,我们定义了抽象者实例,并将其实例化为具体的支付平台:微信支付和支付宝支付。然后在平台的构造函数中调用所需的鉴权处理类。最后调用pay()方法进行支付。这就使用了桥接模式将平台与支付鉴权模式进行桥接,大大减小了代码耦合度。

最终运行结果如下:

Java设计模式再相识 (八)——桥接模式_第1张图片

桥接模式的优缺点

优点

  • 满足单依职责和开闭原则。
  • 提高项目的可拓展性,给后续需求预留了扩展空间。

缺点

  • 过度使用可能造成代码复杂度提升,增加开发的难度。

总结

本例以微信和支付宝支付为例,详细讲解了桥接模式在微信支付宝中不同支付方法的应用。

本文示例的完整源代码参见:Github

你可能感兴趣的:(设计模式,Java,SpringBoot,java,桥接模式,开发语言,设计模式,后端)