什么是桥接模式
从字面意思看,“桥接”就是用桥去连接的意思,桥建好后,桥两边的世界就可以相互来往了。
岁月更迭,桥本身不会有变化,但是桥两边的世界有无穷的变化,而且,两边的变化彼此独立,互不影响。
就像“灯、电线、开关”这样的实际生活场景,电线就是桥,灯和开关就是桥两边的世界,通过电线把灯和开关连接起来工作,这就是桥接模式。
灯坏了换灯,开关坏了换开关,而且,想换什么样的就换什么样的,换灯的时候不用考虑开关,换开关的时候不用考虑灯,操作起来能这么方便,全都是电线的功劳。
这也就是桥接模式的好处:
通过一座桥,解藕桥两边系统的强关联性,让它们能够独立的变化
试想一下,如果没有电线,直接把开关集成在灯上面,那么,灯和开关任何一个出现问题,两者就都得换,并且,两者紧紧的绑在一起,谁也别想离开谁,不离不弃,生死相依,这就是爱情的模样吧。
生活需要爱情,系统需要自由,玫瑰香水给你甜蜜的爱情,桥接模式给你想要的自由~~
设计与实现
现实生活中,桥能看得见,很好理解,但在编程中,桥是个抽象的概念,并不是一个具体的东西,相对来说,可能会不太好理解。
其实桥接模式很简单,就是编码的时候,抽象与实现分离,灵活运用多态。这也是很多设计模式的精髓所在。
还拿灯和开关举例子,先看看不用桥接模式的话,应该如何设计:
// 一个正常的灯
public class NormalLamp {
public void powerOn() {
System.out.println("开始工作");
}
public void powerOff() {
System.out.println("停止工作");
}
}
// 一个正常的开关
public class NormalSwitch {
private NormalLamp lamp;
public NormalSwitch(NormalLamp lamp) {
this.lamp = lamp;
}
public void turnOn() {
lamp.powerOn();
}
public void turnOff() {
lamp.powerOff();
}
}
// 测试方法
public static void main(String[] args) {
NormalLamp normalLamp = new NormalLamp();
NormalSwitch normalSwitch = new NormalSwitch(normalLamp);
normalSwitch.turnOn();// 开
normalSwitch.turnOff();// 关
}
稍微有点编程经验的人,可能都会看出来,这样的编码风格耦合性太强,灯NormalLamp
和开关NormalSwitch
强关联,换灯就必须换开关。
比如,想换个高级灯AdvancedLamp
,就必须加个高级开关AdvancedSwitch
,因为普通开关NormalSwitch
不支持高级灯的工作。
把这段代码用桥接模式重新设计,体现出抽象和多态的思想:
// 灯的抽象
public interface Lamp {
void powerOn();
void powerOff();
}
// 普通的灯
public class NormalLamp implements Lamp {
@Override
public void powerOn() {
System.out.println("开始工作");
}
@Override
public void powerOff() {
System.out.println("停止工作");
}
}
// 高级的灯
public class AdvancedLamp implements Lamp {
@Override
public void powerOn() {
System.out.println("高级灯开始工作");
}
@Override
public void powerOff() {
System.out.println("高级灯停止工作");
}
}
// 普通的开关
public class NormalSwitch {
private Lamp lamp;
public NormalSwitch(Lamp lamp) {
this.lamp = lamp;
}
@Override
public void turnOn() {
lamp.powerOn();
}
@Override
public void turnOff() {
lamp.powerOff();
}
}
// 测试方法
public static void main(String[] args) {
NormalLamp normalLamp = new NormalLamp();
NormalSwitch normalSwitch = new NormalSwitch(normalLamp);
normalSwitch.turnOn();
normalSwitch.turnOff();
// 换高级灯
AdvancedLamp advancedLamp = new AdvancedLamp();
normalSwitch = new NormalSwitch(advancedLamp);
normalSwitch.turnOn();
normalSwitch.turnOff();
}
这段代码对灯进行了抽象,普通开关NormalSwitch
内部连接着灯的抽象Lamp
,这个连接就是桥,这种编码方法就是桥接模式。
可以说,现在的普通开关NormalSwitch
特别厉害,它能控制所有的灯工作,只需要给它一个具体的灯对象就好。
现在,开关不变,灯可以随便换。
再进一步,如果开关也想多样化,也要自由的更换,那就再对开关也进行一个抽象,运用上多态思想:
// 开关的抽象
public abstract class Switch {
private Lamp lamp;
public Switch(Lamp lamp) {
this.lamp = lamp;
}
public void turnOn() {
lamp.powerOn();
}
public void turnOff() {
lamp.powerOff();
}
}
// 普通开关
public class NormalSwitch extends Switch {
public NormalSwitch(Lamp lamp) {
super(lamp);
}
}
// 高级开关
public class AdvancedSwitch extends Switch {
public AdvancedSwitch(Lamp lamp) {
super(lamp);
}
}
设计到这里,灯和开关就都能自由的更换组合了。
总结
桥接模式的核心是抽象与实现的分离,运用多态机制达到运行时的多样化效果。
本文的桥接模式只涉及到两个维度的变量,灯和开关,如果业务场景复杂,也可能有多个变量维度。
桥接模式是设计模式里面很基础的一种,体现的主要是面向对象语言的两大特性:封装、多态。
设计模式,万变不离其宗:抽象与实现的分离