简介

桥接模式(BridgePattern)是一种结构型设计模式,通过将抽象部分与实现部分分离,把多种可匹配的使用进行组合,从而能在开发时分别使用。

  • 分离抽象实现: 将抽象部分与它的具体实现部分分离,使它们都可以独立的变化;独立的变化就是在一定程度上进行解耦

  • 组合方式: 通过组合的方式建立两个类之间的联系,而不是继承;

桥接模式 相当于使用桥梁将两侧连接起来,这里指的是使用桥梁连接两个类,在两个类之间建立某种联系,可以通过继承,也可以通过组合,桥接模式是采用组合的方式,建立两个类之间的关系;合成复用原则,推荐优先使用组合,不是继承;桥接模式可以防止子类过多,成系统复杂的情况;

桥接模式的重点是理解类的抽象部分具体的实现部分

  • 抽象过程: 抽象部分,经过抽象化,忽略某些信息,将不同的实体当做同一个对待;面向对象中,将对象的共同性质抽取出来,形成类的过程,就是抽象化过程;

  • 实现过程: 对于具体实现的部分,也要进行实现化,针对抽象化,给出具体实现;这个过程就是实现过程,过程的产出就是具体实现部分,具体实现部分产生的对象,比抽象产生的更具体,是对抽象化事物的具体化产物;

应用场景

桥接模式适用场景:

  • 抽象实现灵活:

抽象和具体实现之间,需要增加更多灵活性的情况下,适合使用桥接模式; 使用桥接模式,可以避免在这两个层次之间,建立静态的继承关系,通过桥接模式在二者之间建立关联关系; 抽象和实现都可以各自以继承的方式扩展,互不影响; 可以动态的将抽象的子类对象和实现的子类对象进行组合,在系统中,抽象和实现之间进行了解耦;

  • 独立变化维度:

一个类存在两个或更多的独立变化维度,并且这些维度都需要独立扩展; 抽象部分可以独立扩展,具体实现的部分,也可以独立扩展;

  • 不使用继承:不希望使用继承,或因多层继承导致系统类的个数增加;

优缺点

有点

  • 分离抽象与实现:

分离抽象部分和具体实现部分; 桥接模式使用组合关系解耦了抽象和实现之间的继承关系; 抽象和实现可以格子沿着自己的维度进行扩展; 抽象和实现不在同一个继承层次中,通过进行组合,可以获得多维度的组合对象;

  • 提高扩展型:

提高了系统的可扩展性; 解耦了抽象与实现,二者可以继续进行扩展,不需要改变系统原有的功能;

  • 符合开闭原则;

  • 符合合成复用原则;

缺点

  • 系统复杂: 增加了系统的理解与设计难度;

  • 识别变化维度: 需要正确地识别出系统中,两个独立变化的维度;

  • 桥接模式的使用范围,有一定的局限性;

相关设计模式的区别

桥接模式与组合模式:

组合模式更强调部分与整体间的组合; 桥接模式更强调平行级别上,不同类的组合;

桥接模式与适配器模式:

  • 共同点: 都是让两个类配合工作;

  • 不同点: 二者目的不同;

适配器模式 是改变已有接口,让二者之间相互配合;目的是配合; 桥接模式 分离抽象和具体的实现,目的是分离;

示例讲解

业务逻辑场景: 开发跨平台的视频播放器平台有Android,iOS,Windows,Linux,Mac,播放器支持的格式有MP4,AVI,RMVB,FLV格式;这种情况下,适合使用桥接模式;

平台: 播放器支持Linux,Android平台; 视频格式: 播放器支持MP4,FLV视频格式;

这里分为两块,一块是平台,一块是视频格式; 平台可以不断的扩展,如:Windows,iOS,MAC,嵌入式平台; 视频类型也可以不断的扩展,如:H264,H265,MPEG等; 二者可以随着自己的层级进行扩展;

视频格式抽象

public interface Vedio {
    /**
     * 打开视频
     * 可以打开MP4/FLV格式视频
     * 视频(格式)是个 抽象
     * @return
     */
    Vedio openVedio();
​
    /**
     * 查看视频信息
     */
    void showVedio();
}

FLV视频格式实现

/**
 * FLV视频格式
 */
public class FlvVedio implements Vedio {
    @Override
    public Vedio openVedio() {
        System.out.println("打开FLV格式视频");
        return new FlvVedio();
    }
​
    @Override
    public void showVedio() {
        System.out.println("当前视频格式是FLV");
    }
}

MP4视频格式实现

/**
 * MP4格式
 */
public class MP4Vedio implements Vedio {
    @Override
    public Vedio openVedio() {
        System.out.println("打开MP4格式视频");
        return new MP4Vedio();
    }
​
    @Override
    public void showVedio() {
        System.out.println("当前视频格式是MP4");
    }
}

系统平台抽象

/**
 * 平台操作系统 抽象类
 */
public abstract class Platform {
    /**
     * 这是桥接模式最核心的代码
     * 在 Platform 中通过组合方式关联 Vedio
     * Platform 的子类也可以关联 Vedio 子类
     */
    protected Vedio account;
​
    public Platform(Vedio account) {
        this.account = account;
    }
​
    /**
     * 该方法与 Vedio 中的方法名相同
     * 方法名相同不是强制的
     * @return
     */
    abstract Vedio openVedio();
}

Linux系统平台实现

public class LinuxPlatform extends Platform {
    public LinuxPlatform(Vedio account) {
        super(account);
    }
​
    @Override
    Vedio openVedio() {
        System.out.println("在Linux平台播放视频");
        return account;
    }
}

Android系统平台实现

public class AndroidPlatform extends Platform {
    public AndroidPlatform(Vedio account) {
        super(account);
    }
​
    @Override
    Vedio openVedio() {
        System.out.println("在Android平台打开视频");
        return account;
    }
}

客户端测试类

public class Main {
    public static void main(String[] args) {
        // 在Linux平台打开FLV视频
        Platform linuxPlatform = new LinuxPlatform(new FlvVedio());
        Vedio linuxFlv = linuxPlatform.openVedio();
        linuxFlv.showVedio();
​
        System.out.println();
​
        // 在Android平台打开MP4视频
        Platform androidPlatform = new AndroidPlatform(new MP4Vedio());
        Vedio androidMp4 = androidPlatform.openVedio();
        androidMp4.showVedio();
    }
}

测试结果

在Linux平台播放视频
当前视频格式是FLV
​
在 Android 平台打开视频
当前视频格式是MP4