桥接模式Abstraction 和 Implementor 的理解
在图书馆看到一本 通过电商项目真正实战《贯穿设计模式》。拿起来翻到了 桥接模式,感觉味道不对,和我印象中不一样。
感谢这位同学提供的源码
贯穿设计模式-适配器模式+桥接模式_-CSDN博客GitHub - WeiXiao-Hyy/design-patterns: 《贯穿设计模式》学习笔记
Clone下来生成如下 Class Diagram。
和wikipedia 上的 桥接模式类图(下图),对比一下就发现,书的作者对桥接模式的运用有点儿“独特风格”。似乎认为 abstraction 和 implementor 是同一个纬度,而同一纬度并不适合桥接模式。
Abstraction (abstract class) 【(抽象类)】
defines the abstract interface 【定义抽象的接口】
maintains the Implementor reference. 【持有一个Implementor 的引用】
RefinedAbstraction (normal class) 【(普通类)】
extends the interface defined by Abstraction 【扩展了 Abstraction 功能】
Implementor (interface) 【实施者(接口)】
defines the interface for implementation classes 【给 ConcreteImplementor 定义接口】
ConcreteImplementor (normal class) 【具体实施者(普通类)】
implements the Implementor interface 【实现 Implementor 接口】
刚接触的桥接模式时,觉得很难理解,现在想想其实是对 Abstraction 和 Implementor 的理解出了问题。
DeepSeek 给的解释是:
抽象类(Abstraction):定义高层逻辑,并持有一个对实现类的引用。
扩展抽象类(Refined Abstraction):对抽象类的扩展,通常增加更多的功能。
实现类接口(Implementor):定义实现部分的接口,抽象类通过该接口调用具体的实现。
具体实现类(Concrete Implementor):实现实现类接口,提供具体的实现细节。
第一次看了,会不会觉得这里的 “实现类 Implementor” 就是这里 “抽象类 Abstraction” 的实现呢!如果这么认为就无法理解 bridge pattern了。并非java中的抽象类和实现类。
Abstraction 和 Implementor 的关系
分离抽象与实现:Abstraction 和 Implementor 是两个独立的维度,Abstraction 依赖于 Implementor 的接口,但不需要知道具体的实现细节。
组合关系:Abstraction 通过组合的方式持有一个 Implementor 的引用,并将具体的操作委托给 Implementor。
独立变化:Abstraction 和 Implementor 可以独立扩展和修改,而不会相互影响。
对的,是组合关系,并非继承 🤣,而且是两个纬度。
这里推荐 设计模式之桥接模式(Bridge)-CSDN博客 中的支付工具和支付方式的例子。
来看一个 Pizza 的例子
在一个地方,开了一家Pizza店, 有两个不同的口味。
PepperoniPizza extends Pizza
VeggiePizza extends Pizza
生意不错,分别在美国和意大利开了店,根据店铺 和 口味,两个维度,扩展到 4个 Pizza 实现。
ItalianVeggiePizza extends Pizza
ItalianPepperoniPizza extends Pizza
AmericanVeggiePizza extends Pizza
AmericanPepperoniPizza extends Pizza
后续如果增加 Chicken Pizza,则要同时增加两种实现。 无法相信随着口味和店铺的扩增,将会成倍增长。
导致此问题的原因是我们尝试从两个不同的维度扩展 pizza 。解决此问题则需要采用 组合(composition) 而非 继承(inheritance)。
也就是说需要,提取其中一个纬度,采用不同的 class hierarchy。原有的class持有新的 hierarchy 的引用。
通过这种方式,我们需要 定义 Restaurant abstract class,提供 ItalianRestaurant 和 AmericanRestaurant 两个实现类。Pizza 对象引用则被 Restaurant 持有,来充当 bridge。
AmericanRestaurant americanRestaurant = new AmericanRestaurant(new PepperoniPizza());
americanRestaurant.deliver();ItalianRestaurant italianRestaurant = new ItalianRestaurant(new VeggiePizza());
italianRestaurant.deliver();
DeepSeek给出的解释
桥接模式(Bridge Pattern)是一种结构型设计模式,旨在将抽象部分与实现部分分离,使它们可以独立变化。为了更好地理解桥接模式,可以从以下几个方面入手:
1. 核心思想
桥接模式的核心在于解耦。它将抽象部分(通常是高层逻辑)与实现部分(通常是底层细节)分离,使它们可以独立扩展和修改,而不会相互影响。
2. 适用场景
-
当你有多个维度的变化时,桥接模式可以帮助你避免类爆炸问题。
-
当你希望抽象部分和实现部分可以独立扩展时。
-
当你希望在运行时切换实现部分时。
3. 结构
桥接模式通常包含以下角色:
-
抽象类(Abstraction):定义高层逻辑,并持有一个对实现类的引用。
-
扩展抽象类(Refined Abstraction):对抽象类的扩展,通常增加更多的功能。
-
实现类接口(Implementor):定义实现部分的接口,抽象类通过该接口调用具体的实现。
-
具体实现类(Concrete Implementor):实现实现类接口,提供具体的实现细节。
4. 示例
假设你有一个图形绘制系统,支持多种形状(如圆形、矩形)和多种颜色(如红色、蓝色)。如果不使用桥接模式,你可能需要为每种形状和颜色的组合创建一个类(如红色圆形、蓝色矩形等),这会导致类爆炸。
使用桥接模式,你可以将形状和颜色分离:
-
抽象类:形状(Shape)
-
扩展抽象类:圆形(Circle)、矩形(Rectangle)
-
实现类接口:颜色(Color)
-
具体实现类:红色(Red)、蓝色(Blue)
// 实现类接口
interface Color {void applyColor();
}// 具体实现类
class Red implements Color {@Overridepublic void applyColor() {System.out.println("Applying red color");}
}class Blue implements Color {@Overridepublic void applyColor() {System.out.println("Applying blue color");}
}// 抽象类
abstract class Shape {protected Color color;public Shape(Color color) {this.color = color;}abstract void draw();
}// 扩展抽象类
class Circle extends Shape {public Circle(Color color) {super(color);}@Overridevoid draw() {System.out.print("Drawing Circle: ");color.applyColor();}
}class Rectangle extends Shape {public Rectangle(Color color) {super(color);}@Overridevoid draw() {System.out.print("Drawing Rectangle: ");color.applyColor();}
}// 客户端代码
public class BridgePatternDemo {public static void main(String[] args) {Shape redCircle = new Circle(new Red());Shape blueRectangle = new Rectangle(new Blue());redCircle.draw();blueRectangle.draw();}
}
5. 优点
-
解耦:抽象和实现可以独立变化,互不影响。
-
扩展性:可以轻松扩展新的抽象类或实现类。
-
减少类爆炸:避免了为每个组合创建单独的类。
6. 缺点
-
复杂性增加:引入了更多的类和接口,增加了系统的复杂性。
-
理解难度:对于初学者来说,桥接模式可能较难理解。
7. 与其他模式的关系
-
与适配器模式:适配器模式通常用于使不兼容的接口兼容,而桥接模式用于将抽象与实现分离。
-
与策略模式:策略模式侧重于算法的替换,而桥接模式侧重于抽象与实现的分离。
8. 总结
桥接模式通过将抽象与实现分离,提供了一种灵活的方式来处理多维度的变化。理解桥接模式的关键在于认识到它的解耦思想,并通过实际例子来体会其应用场景和优势。