桥接模式
# 什么是桥接模式
- 官方定义
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。将抽象和实现解耦,让它们可以独立变化。
这里我们需要注意关键字:抽象化与实现化解耦。这里的抽象化并不是指抽象类或者接口,而是指的业务中的抽象;实现化也不是指接口的实现,而是指的业务中的实现。
具体分析:
理解桥接模式,重点需要理解如何将抽象化(Abstraction)与实现化(Implementation)脱耦,使得二者可以独立地变化。
抽象化:抽象化就是忽略一些信息,把不同的实体当作同样的实体对待。在面向对象中,将对象的共同性质抽取出来形成类的过程即为抽象化的过程。
实现化:针对抽象化给出的具体实现,就是实现化,抽象化与实现化是一对互逆的概念,实现化产生的对象比抽象化更具体,是对抽象化事物的进一步具体化的产物。
脱耦:脱耦就是将抽象化和实现化之间的耦合解脱开,或者说是将它们之间的强关联 (opens new window)改换成弱关联,将两个角色之间的继承关系改为关联关系。桥接模式中的所谓脱耦,就是指在一个软件系统的抽象化和实现化之间使用关联关系(组合或者聚合)而不是继承,从而使两者可以相对独立地变化,这就是桥接模式的用意。
也可理解成:“一个类存在两个(或多个)独立变化的维度,通过组合,让这两个(或多个)维度可独立进行扩展。”组合替代继承,就能避免继承层次的指数级爆炸,即“组合优于继承”设计原则。
# UML
Abstraction
: 定义抽象类的接口,维护一个指向Implementor类型对象的指针,将Client的请求转发给它的Implementor.RefinedAbstraction扩充由Abstraction定义的接口.定义了基于基本操作的较高层次的操作
RefinedAbstraction
: 扩充由Abstraction定义的接口而得的 抽象类 (opens new window)
Implementor
: 定义实现类的接口.仅提供基本操作
ConcreteImplementor
:实现Implementor接口并定义它的具体实现
核心是:抽象化与实现化分离,组合代替继承
# 具体demo
假如现在有一个几何 形状
Shape类, 从它能扩展出两个子类: 圆形
Circle和 方形
Square 。 你希望对这样的类层次结构进行扩展以使其包含颜色, 所以你打算创建名为 红色
Red和 蓝色
Blue的形状子类。 但是, 由于你已有两个子类, 所以总共需要创建四个类才能覆盖所有组合, 例如 蓝色圆形
BlueCircle和 红色方形
RedSquare 。
或是
这样使用继承来扩展的结果,就是让所有的实现类的数量将以集合级数的增长。
怎么解决呢?
问题的根本原因是我们试图在两个独立的维度——形状与颜色——上扩展形状类。 这在处理类继承时是很常见的问题。
桥接模式通过将继承改为组合的方式来解决这个问题。 具体来说, 就是抽取其中一个维度并使之成为独立的类层次, 这样就可以在初始类中引用这个新层次的对象, 从而使得一个类不必拥有所有的状态和行为。
将一个类层次转化为多个相关的类层次, 避免单个类层次的失控。
根据该方法, 我们可以将颜色相关的代码抽取到拥有 红色
和 蓝色
两个子类的颜色类中, 然后在 形状
类中添加一个指向某一颜色对象的引用成员变量。 现在, 形状类可以将所有与颜色相关的工作委派给连入的颜色对象。 这样的引用就成为了 形状
和 颜色
之间的桥梁。 此后, 新增颜色将不再需要修改形状的类层次, 反之亦然。
# 源码中的桥接模式
JDBC 中的设计模式就用到了桥接模式
那在JDBC的设计中,什么是“抽象”,什么是“实现”呢?JDBC抽象出来的那套API就是抽象,不同数据库服务商实现的Driver就是实现。所以桥接模式中的抽象并不是指一个接口,它可能是设计出来的一套跟数据库操作相关的API。而具体的实现也不是一个接口,也可能是一套API,就像Driver中的connect,execute等方法。最后抽象和实现彻底分开,以组合这种弱关联的方式让两者相互合作,增强灵活性,避免继承层次的指数级爆炸。其实调用到最后,DriverManager都是委托具体的Driver干活的(connect,execute)
# 桥接模式和策略模式区别
桥接模式
策略模式
形式上的不同
两者还是有一定区别的,对比两幅结构图,我们可以发现,在桥接模式中不仅Implementor具有变化 (ConcreateImplementior),而且Abstraction也可以发生变化(RefinedAbstraction),而且两者的变化 是完全独立的,RefinedAbstraction与ConcreateImplementior之间松散耦合,它们仅仅通过Abstraction与 Implementor之间的关系联系起来。而在策略模式中,并不考虑Context的变化,只有算法的可替代性。
语意上的不同
桥接模式强调Implementor接口仅提供基本操作,而Abstraction则基于这些基本操作定义更高层次的操作。而策略模式强调 Strategy抽象接口的提供的是一种算法,一般是无状态、无数据的,而Context则简单调用这些算法完成其操作。
策略模式,桥接模式要表达的内容要更多,结构也更加复杂。
# 参考
https://cloud.tencent.com/developer/article/1431446
https://juejin.cn/post/7066448550506266661
https://cloud.tencent.com/developer/article/1817106
https://www.modb.pro/db/151037
https://www.zhihu.com/question/67735508
https://refactoringguru.cn/design-patterns/bridge