1. 概念
桥接模式是一种结构型设计模式, 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构, 从而能在开发时分别使用。
这个模式个人感觉十分简单,它的使用场景也很清晰没那么模糊,还是先从一个假设的问题引入。假如现在有一个几何类Shape
,它扩展出两个子类圆形Circle
和方形Square
。 然后你又希望扩展出两个颜色,红色Red
和蓝色Blue
的形状子类。
但是,由于你已有两个子类,所以总共需要创建四个类才能覆盖所有组合, 例如蓝色圆形BlueCircle
和红色方形RedSquare
。这个时候,很明显存在一个问题:类爆炸,假如我新增一种颜色,就得同时增加两个新的类,一旦有多种颜色多种形状,那子类个数就是颜色 X 形状,这谁顶得住。
同时这里也不单单只有类爆炸的问题,假如圆形的方法需要做出修改,那么蓝色圆形和红色圆形的代码也需要做出相应变化。牵一发而动全身。
那如何解决这种情况呢?这个问题的根本原因是我们把两个维度的东西混在一起解决了,造成了发生一点改动,就会同时修改两个维度的内容,所以我们需要把两个维度独立出去。让每个维度的修改都发生在各自维度里面。
将一个类层次转化为多个相关的类层次, 避免单个类层次的失控。比如上面的几何类,我们把颜色和形状抽象成两个维度,然后对形状使用抽象类,颜色使用接口分成两个维度,然后使用组合的方式把他们联合起来,这样一旦要新增某个颜色或者某个形状,只需要在彼此维度里面新增一个类就OK了,而不需要大规模新增类,解决了类爆炸问题。
且一旦代码需要修改,也只是修改某一个维度的代码即可,不需要改动全部类的代码,也解决了牵一发动全身的问题。
这就是桥接模式,关于桥接模式的使用还有一个问题,就是什么维度可以作为抽象,什么维度可以作为实现。个人理解,这个应该没有明确的区分,主要看应用场景,看我们对哪个维度有需求客户端要使用哪个维度,就将哪个维度作为抽象,另外一个维度作为接口。这一点听不懂可以看下下面代码-,-
比如上面几何类那个例子,我们如果客户端要使用的是形状,那就把形状作为抽象,颜色作为接口;那如果我们客户端要使用的是颜色,那我们就可以把颜色做成抽象,把形状当作接口。
其实桥接模式也不仅仅只能支持两个维度,也可以支持多个维度,比如现在几何类里面加入一个尺寸Size
,现在抽象是形状,颜色和尺寸做接口,都组合进形状,这样就连接起了三个维度。
还有一点需要注意,就是有些人会将桥接模式和其他模式一起混淆,比如适配器模式,桥接模式通常会于开发前期进行设计, 使你能够将程序的各个部分独立开来以便开发。 另一方面, 适配器模式通常在已有程序中使用, 让相互不兼容的类能很好地合作。
- 总结
- 桥接模式遵循了单一原则,负责分离一个类复杂的耦合,分成多个维度。
- 桥接模式不单单只能桥接两个维度,也可以连接多个维度。
- 桥接模式包含两个模块,抽象与实现,应该把要具体使用的维度作为抽象,补充功能作为实现。
2. 特点
-
优点
- 可以创建与平台无关的类和程序。
- 客户端代码仅与高层抽象部分进行互动, 不会接触到平台的详细信息(接口实现的功能)。
- 开闭原则。 你可以新增抽象部分和实现部分, 且它们之间不会相互影响。
- 单一职责原则。 抽象部分专注于处理高层逻辑, 实现部分处理平台细节。
-
缺点
- 对高内聚的类使用该模式可能会让代码更加复杂。
-
使用场景
-
如果你想要拆分或重组一个具有多重功能的庞杂类 (例如能与多个数据库服务器进行交互的类), 可以使用桥接模式。
类的代码行数越多, 弄清其运作方式就越困难, 对其进行修改所花费的时间就越长。 一个功能上的变化可能需要在整个类范围内进行修改, 而且常常会产生错误, 甚至还会有一些严重的副作用。
桥接模式可以将庞杂类拆分为几个类层次结构。 此后, 你可以修改任意一个类层次结构而不会影响到其他类层次结构。 这种方法可以简化代码的维护工作, 并将修改已有代码的风险降到最低。
-
如果你希望在几个独立维度上扩展一个类, 可使用该模式。
桥接建议将每个维度抽取为独立的类层次。 初始类将相关工作委派给属于对应类层次的对象, 无需自己完成所有工作。
-
如果你需要在运行时切换不同实现方法, 可使用桥接模式。
当然并不是说一定要实现这一点, 桥接模式可替换抽象部分中的实现对象, 具体操作就和给成员变量赋新值一样简单。顺便提一句, 最后一点是很多人混淆桥接模式和策略模式的主要原因。
-
3. 实现
- UML类图
- Java代码
1.抽象类
2.抽象子类/** * @Author: chy * @Description: 抽象类:几何类 * @Date: Create in 11:45 2021/3/8 */ public abstract class Shape { // 内置接口 protected Color color; public Shape(Color color) { this.color = color; } protected abstract void showShape(); }
/** * @Author: chy * @Description: 抽象类的继承:原型类 * @Date: Create in 11:47 2021/3/8 */ public class Circle extends Shape{ public Circle(Color color) { super(color); } @Override protected void showShape() { color.showColor(); System.out.println("我是圆形"); } }
3.接口/** * @Author: chy * @Description: 抽象继承:方形类 * @Date: Create in 15:00 2021/3/8 */ public class Square extends Shape{ public Square(Color color) { super(color); } @Override protected void showShape() { color.showColor(); System.out.println("我是方形"); } }
4.接口实现类/** * @Author: chy * @Description: 接口:颜色 * @Date: Create in 11:46 2021/3/8 */ public interface Color { void showColor(); }
/** * @Author: chy * @Description: 接口实现:蓝色 * @Date: Create in 14:57 2021/3/8 */ public class Blue implements Color{ @Override public void showColor() { System.out.println("我是蓝色"); } }
5.客户端/** * @Author: chy * @Description: 接口实现:红色 * @Date: Create in 11:48 2021/3/8 */ public class Red implements Color{ @Override public void showColor() { System.out.println("我是红色"); } }
/** * @Author: chy * @Description: 客户端 * @Date: Create in 11:49 2021/3/8 */ public class Client { public static void main(String[] args) { // 红色圆形 Circle circle = new Circle(new Red()); circle.showShape(); // 蓝色方形 Square square = new Square(new Blue()); square.showShape(); } }