1.桥接模式介绍
1.1 定义
桥接模式是一种结构型设计模式,它的主要目的是将抽象部分与实现部分分离,通过组合的方式实现二者解耦,使它们可以独立地变化。
其中:
- 抽象部分:描述“是什么”和“做什么”。通常是指对事物的高层次描述,它定义了事物的核心功能和行为,而不关心具体的实现细节。抽象通常比较稳定,因为它描述的是核心功能。
- 实现部分:描述“怎么做”。是抽象部分定义功能的具体执行者,它提供了具体的代码来完成抽象所定义的行为。实现可能经常变化,因为它涉及具体的技术和业务逻辑。
1.2 举例说明
这里以“遥控器和电视机”的例子来说明桥接模式的功能。
1.2.1 没有“桥接模式”之前:
我们可能会这样做:
- 你买了一台索尼电视,它配了一个索尼普通遥控器。
- 后来你又买了一台三星电视,它配了一个三星普通遥控器。
但问题来了:你觉得普通遥控器功能太少,想换个“智能遥控器”(比如带语音控制的)。这时你会发现:
- 你需要一个 “索尼智能遥控器” 去控制索尼电视。
- 你需要一个 “三星智能遥控器” 去控制三星电视。
- 如果将来又出了个“小米电视”,你又需要一个 “小米智能遥控器”。
你看,遥控器的“类型”(普通、智能)和电视机的“品牌”(索尼、三星、小米)被死死地绑在了一起。每增加一个遥控器类型,或者每增加一个电视品牌,你就得新增一大堆对应的遥控器。这就叫 “类爆炸”,非常不灵活。
1.2.2 有桥接模式:万能遥控器
桥接模式就像是发明了 “万能遥控器”。它的思路是这样的:
“遥控器的功能” 和 “电视机具体怎么执行这个功能” 是两件独立的事情,我们应该把它们分开!
于是,我们有了两个独立的东西:
抽象部分(Abstractions):遥控器
- 它只管定义“有什么功能”,比如:开机、关机、换台。
- 它可以有不同的类型,比如:
普通遥控器
(只有基本功能)智能遥控器
(在基本功能上,增加了语音控制)
实现部分(Implementations):电视机
- 它只管“具体怎么干活”。
- 不同品牌的电视机,执行同一个命令的方式可能完全不同(比如它们的红外码不一样)。
索尼电视
的开机方法。三星电视
的开机方法。小米电视
的开机方法。
那么,“桥”在哪里呢?
这个“桥”,就是把遥控器和电视机连接起来的机制。在万能遥控器内部,有一个“插槽”,你可以把具体的“电视机驱动”(也就是实现部分)插进去。
- 当你的智能遥控器想控制索尼电视时,它就把“索尼电视的驱动”加载进来。你按“开机”按钮,遥控器就会调用索尼电视的开机方法。
- 明天你想用这个智能遥控器去控制三星电视,没问题,把驱动换成“三星电视的驱动”就行了。你再按“开机”,遥控器就会去调用三星电视的开机方法。
1.2.3 桥接模式的好处
通过这座“桥”,我们成功地将两个原本纠缠在一起的维度分开了:
- 维度一:遥控器的功能层级 (普通遥控器 -> 智能遥控器 -> 未来可能的全息遥控器)
- 维度二:电视机的具体品牌 (索尼 -> 三星 -> 小米 -> 华为)
这两个维度现在可以独立发展,互不影响。
- 你想升级遥控器?没问题,买个新的智能遥控器就行,它照样能控制你家的所有旧电视。
- 你想换个新电视?也没问题,你手里的旧遥控器,只要配对一下,照样能控制新电视。
用一句话概括:桥接模式就像一座桥,将“做什么”(抽象)和“怎么做”(实现)分置于河的两岸,让它们可以各自独立地变化和发展,但又通过这座桥保持连接。
它的核心思想就是 “解耦” (Decoupling),避免因为一个维度的变化,导致另一个维度也要跟着做大量的修改。
2. 代码演示
2.1 桥接模式演示
2.1.1 实现部分:电视机
//实现部分接口
public interface TV {
void on();
void off();
void tuneChannel(int channel);
}
//具体的实现部分
//索尼品牌的电视
public class SonyTV implements TV {
@Override
public void on() {
System.out.println("Sony TV is turned on.");
}
@Override
public void off() {
System.out.println("Sony TV is turned off.");
}
@Override
public void tuneChannel(int channel) {
System.out.println("Sony TV tuned to channel " + channel);
}
}
//三星品牌的电视
public class SamsungTV implements TV {
@Override
public void on() {
System.out.println("Samsung TV is turned on.");
}
@Override
public void off() {
System.out.println("Samsung TV is turned off.");
}
@Override
public void tuneChannel(int channel) {
System.out.println("Samsung TV tuned to channel " + channel);
}
}
2.2.2 抽象部分:遥控器
//抽象部分
public abstract class RemoteControl {
protected TV tv;
public RemoteControl(TV tv) {
this.tv = tv;
}
public abstract void turnOn();
public abstract void turnOff();
public abstract void setChannel(int channel);
}
//具体抽象部分
public class BasicRemoteControl extends RemoteControl {
public BasicRemoteControl(TV tv) {
super(tv);
}
@Override
public void turnOn() {
tv.on();
}
@Override
public void turnOff() {
tv.off();
}
@Override
public void setChannel(int channel) {
tv.tuneChannel(channel);
}
}
2.2.3 使用Demo
使用遥控器控制各种品牌电视机:
public class BridgePatternDemo {
public static void main(String[] args) {
TV sonyTV = new SonyTV();
RemoteControl sonyRemote = new BasicRemoteControl(sonyTV);
sonyRemote.turnOn();
sonyRemote.setChannel(5);
sonyRemote.turnOff();
TV samsungTV = new SamsungTV();
RemoteControl samsungRemote = new BasicRemoteControl(samsungTV);
samsungRemote.turnOn();
samsungRemote.setChannel(10);
samsungRemote.turnOff();
}
}
2.2 桥接模式应对变化
2.2.1 实现部分:变化
市场又出了一款小米电视机,电视机(实现部分)的品牌变化,不影响遥控器(抽象部分)的使用。
//新出现一款小米品牌的电视
public class XiaomiTV implements TV {
@Override
public void on() {
System.out.println("Xiaomi TV is turned on.");
}
@Override
public void off() {
System.out.println("Xiaomi TV is turned off.");
}
@Override
public void tuneChannel(int channel) {
System.out.println("Xiaomi TV tuned to channel " + channel);
}
}
使用遥控器控制小米电视:
public class BridgePatternDemo {
public static void main(String[] args) {
TV sonyTV = new SonyTV();
RemoteControl sonyRemote = new BasicRemoteControl(sonyTV);
sonyRemote.turnOn();
sonyRemote.setChannel(5);
sonyRemote.turnOff();
TV samsungTV = new SamsungTV();
RemoteControl samsungRemote = new BasicRemoteControl(samsungTV);
samsungRemote.turnOn();
samsungRemote.setChannel(10);
samsungRemote.turnOff();
//新增对小米电视的控制
TV xiaomiTV = new XiaomiTV();
RemoteControl samsungRemote = new BasicRemoteControl(xiaomiTV);
samsungRemote.turnOn();
samsungRemote.setChannel(10);
samsungRemote.turnOff();
}
}
2.2.2 抽象部分:变化
普通遥控器已经满足不了需求,需要一款能语音控制的智能遥控器。遥控器(抽象部分)的演进,不影响电视机(实现部分)的使用。
//新的抽象部分:智能遥控器 (在基本功能上,增加了语音控制)
public abstract class AdvancedRemoteControl extends RemoteControl {
public AdvancedRemoteControl(TV tv) {
super(tv);
}
public abstract void turnOnByVoice();
public abstract void turnOffByVoice();
public abstract void setChannelByVoice(int channel);
}
//具体新的抽象部分:智能遥控器
public class SmartRemoteControl extends AdvancedRemoteControl {
public SmartRemoteControl(TV tv) {
super(tv);
}
@Override
public void turnOn() {
tv.on();
}
@Override
public void turnOff() {
tv.off();
}
@Override
public void setChannel(int channel) {
tv.tuneChannel(channel);
}
@Override
public void turnOnByVoice() {
tv.on();
}
@Override
public void turnOffByVoice() {
tv.off();
}
@Override
public void setChannelByVoice(int channel) {
tv.tuneChannel(channel);
}
}
使用智能遥控器控制三星电视机:
public class BridgePatternDemo {
public static void main(String[] args) {
TV sonyTV = new SonyTV();
RemoteControl sonyRemote = new BasicRemoteControl(sonyTV);
sonyRemote.turnOn();
sonyRemote.setChannel(5);
sonyRemote.turnOff();
TV samsungTV = new SamsungTV();
RemoteControl samsungRemote = new BasicRemoteControl(samsungTV);
samsungRemote.turnOn();
samsungRemote.setChannel(10);
samsungRemote.turnOff();
// 使用智能遥控器
AdvancedRemoteControl smartRemote = new SmartRemoteControl(samsungTV);
smartRemote.turnOn();
smartRemote.setChannel(10);
smartRemote.turnOff();
smartRemote.turnOnByVoice();
smartRemote.setChannelByVoice(20);
smartRemote.turnOffByVoice();
}
}
2.3 总结
在上述例子中,TV
接口和它的实现类代表了实现部分,而RemoteControl
抽象类和它的具体实现类代表了抽象部分。
通过这种分离,抽象定义了系统的功能接口,而实现则负责具体的操作细节。因此,它们可以独立变化:新的电视品牌可以通过实现TV
接口添加,而遥控器的新功能可以通过扩展RemoteControl
类来实现,而不会相互影响。