桥接模式(Bridge Pattern)可以构建独立增长的灵活层次结构,使其更加可扩展和可维护。
问题提出
假设我们构建一个通用的遥控器APP,用于控制各种品牌的电视机。
遥控器有不同类型,比如:基本型RemoteControl、高级型AdvancedRemoteControl、影片型MovieRemoteControl等。基本型有turnOn和turnOff方法,高级型有setChannel方法,影片型有play、pause、rewind等方法。这些方法目前是没法知道如何工作的,只有到设计具体的电视机时才知道,所以这些方法是抽象(abstract)方法,相应地,类也是抽象类。
创建类RemoteControl和类AdvancedRemoteControl。
现在我们要创建具体品牌如Sony电视的遥控器,它有基本型和高级型,实际场景的层次结构可能如上图的注释所示:Sony的基本型遥控器SonyRemoteControl继承于RemoteControl,Sony高级型的遥控器SonyAdvancedRemoteControl则继承于AdvancedRemoteControl。
我们来创建下。
目前我们有两种类型的遥控器,即基本型和高级型,当需要添加一种品牌如Sumsung的遥控器时,我们需要为这两种类型各添加一个继承类,分别为SumsungRemoteControl和SumsungAdvancedRemoteControl。
如果有三种类型比如添加一种类型MovieRemoteControl,那么添加一种品牌比如LG遥控器时,我们就需要添加三个类。当类型越来越多、品牌越来越多时,我们的应用程序将变得很复杂。
这就需要用到桥接模式(Bridge Pattern)。
使用桥接模式,我们可以构建一个简单而灵活的层次结构。
解决方案
当前的结构是这样的。
这个结构的问题前面已说过,非常不灵活。我们的层次会在两个维度进行增长。
如上图,蓝色标出的是关于功能特性的类,这是一个维度。其他的则是关于不同电视品牌的实现,也是一个维度。我们添加功能特性或添加品牌时,两个维度都会增长,这造成了该结构的不灵活。
我们打破它,将该结构一分为二!
为了描述得更清楚些,我们将右侧的RemoteControl改名为Device,SonyRemote改成SonyTV。
目前,左侧和右侧的结构是完全独立的,我们添加组合关系将它们连接起来。
改造之后,左侧添加功能特性不会影响到右侧具体的电视品牌的实现,左侧只依赖右侧的接口或者抽象类。
同样的,右侧添加不同的电视品牌的实现也不会影响左侧的功能特性。
RemoteControl的方法比如turnOn方法调用device的turnOn方法来实现相应的功能。
利用这个结构,我们能组合这两个不同层次结构的各种各样的类,非常灵活。
这个就被称为桥接模式(Bridge Pattern)。
之所以叫这个名字是因为这两个层次结构之间的这种关系,这种关系就像一座桥梁,它连接了两个完全独立的层次结构。
使用桥接模式,我们可以构建可以独立增长的灵活层次结构,使其更加可扩展和可维护。
代码实现
我们来分离当前的层次结构,首先是表现不同品牌的电视的层次结构。
创建接口Device,它有turnOn,turnOff,setChannel方法。
创建具体的电视品牌SonyTV实现Device接口。
现在来处理功能特性的层次。
修改RemoteControl类。清除abstract标识,因为它不再是抽象类。添加device属性,并在构造函数中初始化它,这个device就是连接两个独立层次结构的桥梁。在turnOn方法里,调用device的turnOn方法。在turnOff里,调用device的turnOff方法。
RemoteControl不关心具体的电视品牌,只要是符合Device接口就行,这样我们就不必使用两个维度互相依赖的丑陋结构了。
device属性我们设置为protected,这样可以在RemoteControl的扩展类中使用。
再修改AdvancedRemoteControl类,同样去掉abstract标记,setChannel方法也调用device的setChannel方法。
现在,不同品牌的设备层次结构和功能特性层次结构已完全独立了,我们可以删掉丑陋的SonyAdvancedRemoteControl和SonyRemoteControl了。
再到Main类,合并使用这两个独立层次结构的各种类。
如果我们要添加三星Samsung电视,也是非常方便的。
添加SamsungTV类实现Device接口即可,不再需要创建多个类并将它们添加到我们的层次结构中了。再到Main中替换成Samsung对象测试。
小结
桥接模式应用于层次结构在两个不同的维度上同时增长的场景,我们可以将这个丑陋的复杂层次结构拆分为两个可以独立增长的层次结构,使我们的应用程序设计更具可扩展性和可维护性。