Java设计模式之Bridge模式
Bridge模式的应⽤场景
⾯向对象的程序设计(OOP)⾥有类继承(⼦类继承⽗类)的概念,如果⼀个类或接⼝有多个具体实现⼦类,如果这些⼦类具有以下特性:
- 存在相对并列的⼦类属性。
- 存在概念上的交叉。
- 可变性。
我们就可以⽤Bridge模式来对其进⾏抽象与具体,对相关类进⾏重构。
为了容易理解,我们举例说明⼀下,⽐如汽车类(Car),假设有2个⼦类,卡车类(Truck)与公交车类(Bus),它们有[设置引擎]这个动作⾏为,通过不同引擎规格的设置,可以将它们设置为⽐如为1500cc(Car1500),和2000cc(Car2000)的车。
这样,不管是1500cc的卡车还是2000cc的卡车,⼜或是1500cc的公交车还是2000cc的公交车,它们都
可以是汽车类的⼦类,⽽且:- 存在相对并列的⼦类属性。汽车的种类,与汽车引擎规格是汽车的2个并列的属性,没有概念上的重复。
- 存在概念上的交叉。不管是卡车还是公交车,都有1500cc与2000cc引擎规格的车。
- 可变性。除了卡车,公交车之外,可能还有救⽕车;除了有1500cc与2000cc引擎规格的车之外,还可能有2500cc的车等等。
这样⼀来,我们怎么来设计汽车类呢?
⽅法⼀
通过继承设计所有可能存在的⼦类。可能我们会想到下⾯的这种继承关系:
汽车总类:Car
标致307cross汽车⼦类 - 按种类分类:Bus,Truck
汽车⼦类 - 按引擎分类:Bus1500,Bus2000,Truck1500,Truck2000
这样设置引擎这个动作就由各个⼦类加以实现。
中国摩托车论坛但如果以后需要增加⼀种救⽕车(FireCar),以及增加⼀个引擎规格2500cc,需要实现的⼦类将会有:
Bus1500,Bus2000,Bus2500,Truck1500,Truck2000,Truck2500,FireCar1500,FireCar2000,FireCar2500 多达9个。
也就是说,这种设计⽅法,⼦类数⽬将随⼏何级数增长。
⽽且,Bus1500,Truck1500的引擎规格相同,它们的引擎设置动作应该是⼀样的,但现在把它们分成不同的⼦类,难以避免执⾏重复的动作⾏为。
⽅法⼆
分别为Bus以及Truck实现设置不同引擎的⽅法
汽车总类:Car
汽车⼦类:Bus,Truck
然后在Bus类⾥分别提供1500cc以及2000cc引擎的设置⽅法:
Bus extends Car {
public setEngine1500cc();
public setEngine2000cc();
}
在Truck类⾥也分别提供1500cc以及2000cc引擎的设置⽅法:
Truck extends Car {
public setEngine1500cc();
ora汽车public setEngine2000cc();
}
这种情况,⼦类的数量是被控制了。但⼀⽅⾯,如果每增加⼀种引擎规格,需要修改所有的汽车⼦类;另⼀⽅⾯,即使引擎的设置⾏为⼀样,但是不同的汽车⼦类却需要提供完全⼀样的⽅法。
在实际的应⽤开发中,以上2种⽅法都会造成迁⼀发⽽动全⾝,⽽且会存在⼤量的重复代码。
二手保时捷caymanBridge,桥模式:将抽象部分与它的实现部分相分离,使他们可以独⽴的变化。
Abstraction:
抽象部分的接⼝。通常在这个对象⾥⾯,要维护⼀个实现部分的对象引⽤,在抽象对象⾥⾯的⽅法,需要调⽤实现部分的对象来完成。这个对象⾥⾯的⽅法,通常都是跟具体的业务相关的⽅法。
RefinedAbstraction:
扩展抽象部分的接⼝,通常在这些对象⾥⾯,定义跟实际业务相关的⽅法,这些⽅法的实现通常会使⽤Abstraction中定义的⽅法,也可能需要调⽤实现部分的对象来完成。
Implementor:
定义实现部分的接⼝,这个接⼝不⽤和Abstraction⾥⾯的⽅法⼀致,通常是由Implementor接⼝提供基本的操作,⽽Abstraction⾥⾯定义的是基于这些基本操作的业务⽅法,也就是说Abstraction定义了基于这些基本操作的较⾼层次的操作。
ConcreteImplementor:
真正实现Implementor接⼝的对象。
24.2.3  桥接模式⽰例代码
(1)先看看Implementor接⼝的定义,⽰例代码如下:
/**
* 定义实现部分的接⼝,可以与抽象部分接⼝的⽅法不⼀样
*/
public interface Implementor {
/**
* ⽰例⽅法,实现抽象部分需要的某些具体功能
*/
public void operationImpl();
}
(2)再看看Abstraction接⼝的定义,注意⼀点,虽然说是接⼝定义,但其实是实现成为抽象类。⽰例代码如下:/**
* 定义抽象部分的接⼝
*/
public abstract class Abstraction {
/**
* 持有⼀个实现部分的对象
*/
subaru xv
protected Implementor impl;
/**
* 构造⽅法,传⼊实现部分的对象
* @param impl 实现部分的对象
*/
public Abstraction(Implementor impl){
this.impl = impl;
}
/**
* ⽰例操作,实现⼀定的功能,可能需要转调实现部分的具体实现⽅法
*/
public void operation() {
impl.operationImpl();
}
}
无人驾驶系统(3)该来看看具体的实现了,⽰例代码如下:
/**
* 真正的具体实现对象
*/
public class ConcreteImplementorA implements Implementor {
public void operationImpl() {
//真正的实现
}
}
另外⼀个实现,⽰例代码如下:
/**
* 真正的具体实现对象
*/
public class ConcreteImplementorB implements Implementor {
public void operationImpl() {
//真正的实现
}
}
(4)最后来看看扩展Abstraction接⼝的对象实现,⽰例代码如下:/**
* 扩充由Abstraction定义的接⼝功能
*/
public class RefinedAbstraction extends Abstraction {
public RefinedAbstraction(Implementor impl) {
super(impl);
}
/**
* ⽰例操作,实现⼀定的功能
*/
public void otherOperation(){
/
/实现⼀定的功能,可能会使⽤具体实现部分的实现⽅法,
//但是本⽅法更⼤的可能是使⽤Abstraction中定义的⽅法,
//通过组合使⽤Abstraction中定义的⽅法来完成更多的功能
}
}