Java 中的桥接模式:将抽象与实现解耦
大约 4 分钟
也称为
- 句柄/主体
桥接设计模式的意图
桥接设计模式是一种结构型模式,它将抽象与实现解耦,允许两者独立变化。该模式对于开发灵活且可扩展的软件系统至关重要。
桥接模式的详细解释以及现实世界示例
现实世界示例
在 Java 中,桥接模式通常用于 GUI 框架、数据库驱动程序和设备驱动程序。例如,通用遥控器(抽象)可以通过一致的接口操作各种电视品牌(实现)。
想象一个通用遥控器(抽象),它可以操作不同品牌和类型的电视(实现)。遥控器提供了一致的接口,用于执行诸如开/关、更改频道和调节音量等操作。每个电视品牌或类型都有自己对这些操作的具体实现。通过使用桥接模式,遥控器接口与电视实现解耦,使遥控器可以与任何电视机一起使用,而不管其品牌或内部工作原理如何。这种分离允许添加新的电视机型号而无需更改遥控器的代码,并且可以开发不同的遥控器来与同一组电视机一起使用。
通俗地说
桥接模式是关于优先使用组合而不是继承。实现细节从一个层次结构推送到另一个具有单独层次结构的对象。
维基百科说
桥接模式是一种软件工程中使用的一种设计模式,旨在“将抽象与其实现解耦,以便两者可以独立变化”。
Java 中桥接模式的编程示例
想象你拥有一种可以拥有各种附魔的武器,并且你需要将不同的武器与不同的附魔组合在一起。你会如何处理这个问题?你会创建多个每个武器的副本,每个副本都有不同的附魔,还是你会创建单独的附魔并在需要时将它们应用于武器?桥接模式使你能够执行后者。
这里我们有Weapon
层次结构
public interface Weapon {
void wield();
void swing();
void unwield();
Enchantment getEnchantment();
}
public class Sword implements Weapon {
private final Enchantment enchantment;
public Sword(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The sword is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The sword is swung.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The sword is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
public class Hammer implements Weapon {
private final Enchantment enchantment;
public Hammer(Enchantment enchantment) {
this.enchantment = enchantment;
}
@Override
public void wield() {
LOGGER.info("The hammer is wielded.");
enchantment.onActivate();
}
@Override
public void swing() {
LOGGER.info("The hammer is swung.");
enchantment.apply();
}
@Override
public void unwield() {
LOGGER.info("The hammer is unwielded.");
enchantment.onDeactivate();
}
@Override
public Enchantment getEnchantment() {
return enchantment;
}
}
这里有单独的Enchantment
层次结构
public interface Enchantment {
void onActivate();
void apply();
void onDeactivate();
}
public class FlyingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item begins to glow faintly.");
}
@Override
public void apply() {
LOGGER.info("The item flies and strikes the enemies finally returning to owner's hand.");
}
@Override
public void onDeactivate() {
LOGGER.info("The item's glow fades.");
}
}
public class SoulEatingEnchantment implements Enchantment {
@Override
public void onActivate() {
LOGGER.info("The item spreads bloodlust.");
}
@Override
public void apply() {
LOGGER.info("The item eats the soul of enemies.");
}
@Override
public void onDeactivate() {
LOGGER.info("Bloodlust slowly disappears.");
}
}
这里同时展示了这两个层次结构在实际中的应用
public static void main(String[] args) {
LOGGER.info("The knight receives an enchanted sword.");
var enchantedSword = new Sword(new SoulEatingEnchantment());
enchantedSword.wield();
enchantedSword.swing();
enchantedSword.unwield();
LOGGER.info("The valkyrie receives an enchanted hammer.");
var hammer = new Hammer(new FlyingEnchantment());
hammer.wield();
hammer.swing();
hammer.unwield();
}
这是控制台输出。
The knight receives an enchanted sword.
The sword is wielded.
The item spreads bloodlust.
The sword is swung.
The item eats the soul of enemies.
The sword is unwielded.
Bloodlust slowly disappears.
The valkyrie receives an enchanted hammer.
The hammer is wielded.
The item begins to glow faintly.
The hammer is swung.
The item flies and strikes the enemies finally returning to owner's hand.
The hammer is unwielded.
The item's glow fades.
桥接模式类图

何时在 Java 中使用桥接模式
考虑在以下情况下使用桥接模式
- 你需要避免抽象与其实现之间的永久绑定,例如当需要在运行时选择或切换实现时。
- 抽象及其实现都应该可以通过子类化进行扩展,允许对每个组件进行独立扩展。
- 对抽象的实现的更改不应影响客户端,这意味着它们的代码不应需要重新编译。
- 你在层次结构中遇到大量类,表明需要将对象分成两部分,Rumbaugh 将此概念称为“嵌套泛化”。
- 你想在多个对象之间共享实现,可能使用引用计数,同时将此细节隐藏在客户端,例如 Coplien 的 String 类,其中多个对象可以共享同一个字符串表示形式。
桥接模式 Java 教程
Java 中桥接模式的现实世界应用
- GUI 框架,其中抽象是窗口,而实现可以是底层操作系统窗口系统。
- 数据库驱动程序,其中抽象是通用数据库接口,而实现是特定于数据库的驱动程序。
- 设备驱动程序,其中抽象是与设备无关的代码,而实现是与设备相关的代码。
桥接模式的优缺点
优势
- 解耦接口和实现:桥接模式通过将接口(高级操作)与实现(低级操作)分离来增强模块化。
- 改进可扩展性:你可以独立扩展抽象和实现层次结构。
- 隐藏实现细节:客户端只能看到抽象的接口,而不是其实现。
权衡
- 复杂性增加:该模式可能会使系统架构和代码复杂化,特别是对于不熟悉该模式的客户端而言。
- 运行时开销:额外的抽象层可能会引入性能损失,尽管在实践中这通常可以忽略不计。
相关的 Java 设计模式
- 抽象工厂:抽象工厂模式可以与桥接模式一起使用,以创建独立于用于创建其对象的具体类的平台。
- 适配器:适配器模式用于为对象提供不同的接口,而桥接模式用于将对象的接口与其实现分离。
- 组合:桥接模式通常与组合模式一起使用,以对组件的实现细节进行建模。
- 策略:策略模式类似于桥接模式,但具有不同的意图。两种模式都基于组合:策略使用组合来改变类的行为,而桥接使用组合将抽象与其实现分离。