狗哥家电店里有电视,也有音响。柜台上还有普通遥控器和带静音键的遥控器。
遥控器会变,设备也会变。要是把它们全揉进一套继承关系,类很快就多起来。
桥接模式就是把这两边拆开,中间留一座桥。

两个方向都在变化
现在有两种遥控器、两种设备。
最直接的写法,可能会出现电视遥控器、音响遥控器、电视静音遥控器、音响静音遥控器。
再加投影仪,类还得继续补。问题不在某个类难写,而是两个变化方向绑得太紧。
先看关键 UML 图
桥接模式最适合先看类图。
上面一条是遥控器:RemoteControl 可以继续扩展出 MuteRemoteControl。
下面一条是设备:Device 可以有 Tv、Speaker 等实现。
RemoteControl 持有一个 Device。这条组合关系,就是两边的桥。
设备先统一成接口
电视和音响虽然不同,但遥控器需要的操作差不多:开关和音量。
public interface Device {
boolean isEnabled();
void enable();
void disable();
int getVolume();
void setVolume(int volume);
}
Tv 和 Speaker 分别实现这个接口。
public class Tv implements Device {
private boolean enabled;
private int volume = 10;
public void enable() { enabled = true; }
public void disable() { enabled = false; }
public boolean isEnabled() { return enabled; }
public int getVolume() { return volume; }
public void setVolume(int volume) { this.volume = volume; }
}
遥控器只认 Device,不用知道背后是电视还是音响。
遥控器把操作交给设备
RemoteControl 构造时接收一个设备。
public class RemoteControl {
protected final Device device;
public RemoteControl(Device device) {
this.device = device;
}
public void togglePower() {
if (device.isEnabled()) {
device.disable();
} else {
device.enable();
}
}
public void volumeUp() {
device.setVolume(device.getVolume() + 10);
}
}
遥控器负责“按哪个键”,设备负责“具体怎么开、怎么调音量”。两边各忙各的。
新遥控器不用复制设备代码
想加静音键,只扩展遥控器:
public class MuteRemoteControl extends RemoteControl {
public MuteRemoteControl(Device device) {
super(device);
}
public void mute() {
device.setVolume(0);
}
}
这个静音遥控器既能配电视,也能配音响。
Device tv = new Tv();
RemoteControl remote = new RemoteControl(tv);
remote.togglePower();
remote.volumeUp();
Device speaker = new Speaker();
MuteRemoteControl muteRemote = new MuteRemoteControl(speaker);
muteRemote.togglePower();
muteRemote.mute();
输出:
电视开启=true, 音量=20
音响开启=true, 音量=0
桥接和适配器别混了
上一篇适配器模式,是两套已有接口对不上,中间加转换。
桥接模式通常在设计时就把两个变化方向拆开,让它们能分别扩展。
适配器更像解决“接不上”;桥接更像提前避免“绑太死”。
这俩长得有点像,但出发点不一样。
啥时候适合用桥接
如果一个类只有一个变化方向,普通继承已经够用,没必要多拆一层。
当业务里能清楚看见两条独立变化线,而且两边还要自由组合,桥接模式才有价值。
像遥控器和设备、消息类型和发送渠道、图形和绘制方式,都能用这个思路理解。
先把两边分清,再用接口连起来。别一上来就造一堆抽象类,容易把自己绕进去。
狗哥收个尾
桥接模式最关键的地方,是 把两个变化方向拆开。
遥控器可以增加新功能,设备可以增加新类型。RemoteControl 持有 Device,两边通过组合配合,不用为每个组合再写一个类。
下一篇继续聊 组合模式,看看文件夹和文件这种树形结构怎么统一处理。