1. 桥接模式(Bridge Pattern)
Decouple an abstraction from its implemention so that the two can vary independently. (将抽象和实现解耦, 使两者可以独立变化)
桥接模式,也有的称之为桥梁模式.
1.1 核心思想
- 将类的抽象层和实现层分离,可以使得抽象和实现层独立地进行变化
- 可以说是多层继承的替代方案
- 可以解决多个维度独立变化导致复杂的多层继承问题
1.2 桥接模式-类图
桥接模式共有4种角色:
- Abstraction: 抽象化角色, 抽象类. 定义抽象的接口, 并提供一个实现类的引用.
- Implementor:实现化角色, 可以时抽象类也可以是接口. 定义实现类所需的方法和属性.
- ConcreteImplementorA/ConcreteImplementorB: 具体实现类,实现抽象接口
- RefinedAbstraction: 修正抽象化角色,也可以直接就是实现类.
[外链图片转存失败(img-8HPel9Bh-1566895089203)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-bridge-01.png)]
1.3 桥接模式优缺点
- 优点:
- 抽象与实现分离: 实现可以不受抽象的约束,更灵活
- 扩展性强: 抽象类添加抽象方法,只修改抽象层即可, 不影响实现层
- 实现细节透明: 抽象层通过聚合完成了对实现层的封装,用户不知道实现层具体是怎样.
- 缺点: 实现层不再受抽象层约束, 没有了约束力.
1.4 适用场景
- 一个类存在两个独立变化的维度,而这两个维度均需要独立的变化
- 系统不希望采用多层继承增加系统复杂度时
- 希望抽象层和实现层分离时
2. 桥接模式应用示例
我们来模拟汽车组装场景,我们都知道汽车分为很多品牌,如: 尼桑(Nissan), 斯柯达(Skoda)等。 每个品牌旗下都有多种车型, 如轿车和Suv. 每种车型都分为标配,中配,旗舰等配置. 因此汽车便有了三个维度的变化, 品牌, 类型, 配置. 而且这三种配置可以独立变化.
2.1 多层继承类实现分析
如果我们采用多层继承方式来实现, 那么扩展性会非常差. 假如我们变更需求:
- 增加一个品牌-宝马BMW: 需要新增BMWSedanCar 和 BMWSuv, 并实现标配和中配方法
- 增加一个车型-皮卡Trunk: 需要新增TrunkCar, 然后为每个品牌新增对应实现: NissanTrunkCar, SkodaTrunkSuv
- 增加一个配置-旗舰配置: AbsCar 中需新增组装旗舰车型方法constructFlagShipCar(), 其下面所有类都需要新增方法constructFlagShipCar()
[外链图片转存失败(img-OrIiArao-1566895089203)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-bridge-03.png)]
2.2 桥接模式分析
对相同的需求变更,当我们使用桥接模式设计时:
- 增加一个品牌-宝马BMW: 只需新增一个品牌生产者, BMWProducer
- 增加一个车型-皮卡Trunk: 只需新增一种类型TrunkCar
- 增加一个配置-旗舰配置: 只需修改抽象层, 无须修改实现层
[外链图片转存失败(img-7DPxX466-1566895089204)(https://raw.githubusercontent.com/zongf0504/blog-images/master/images/design-parttern/ldp-bridge-02.png)]
2.3 实现角色抽象接口-IBrandProducer
public interface IBrandProducer {
// 安装全景天窗
void buildSunroof();
// 安装全息影像
void buildHologram();
// 安装Boss 音响
void buildBossSound();
}
2.3 实现角色实现类-NissanProducer
public class NissanProducer implements IBrandProducer {
@Override
public void buildSunroof() {
System.out.println("\t尼桑 汽车-安装全景天窗");
}
@Override
public void buildHologram() {
System.out.println("\t尼桑 汽车-安装全息影像");
}
@Override
public void buildBossSound() {
System.out.println("\t尼桑 汽车-安装Boss音响");
}
}
2.4 实现角色实现类-SkodaProducer
public class SkodaProducer implements IBrandProducer {
@Override
public void buildSunroof() {
System.out.println("\t斯柯达 汽车-安装全景天窗");
}
@Override
public void buildHologram() {
System.out.println("\t斯柯达 汽车-安装全息影像");
}
@Override
public void buildBossSound() {
System.out.println("\t斯柯达 汽车-安装Boss音响");
}
}
2.5 抽象角色抽象类-AbsCar
public abstract class AbsCar {
private IBrandProducer brandProducer;
public IBrandProducer getBrandProducer() {
return brandProducer;
}
public void setBrandProducer(IBrandProducer brandProducer) {
this.brandProducer = brandProducer;
}
// 组装标配车型
public abstract void constructBasicCar();
// 组装中配车型
public abstract void constructMiddleCar();
}
2.6 抽象角色实现类-SedanCar
public class SedanCar extends AbsCar{
抽象角色实现类-SedanCar
@Override
public void constructBasicCar() {
System.out.println("轿车组装-标配车型:");
// 安装全息影像
this.getBrandProducer().buildHologram();
}
@Override
public void constructMiddleCar() {
System.out.println("轿车组装-中配车型:");
// 安装全息影像
this.getBrandProducer().buildHologram();
// 安装Boss 音响
this.getBrandProducer().buildBossSound();
}
}
抽象角色实现类-SedanCar
2.7 抽象角色实现类-SuvCar
public class SuvCar extends AbsCar {
@Override
public void constructBasicCar() {
System.out.println("SUV组装-标配车型:");
// 安装全景天窗
this.getBrandProducer().buildSunroof();
}
@Override
public void constructMiddleCar() {
System.out.println("SUV组装-中配车型:");
// 安装全景天窗
this.getBrandProducer().buildSunroof();
// 安装全息影像
this.getBrandProducer().buildHologram();
}
}
2.8 测试
@Test
public void test(){
// 汽车生产者-实现者
IBrandProducer nissanProducer = new SkodaProducer();
//汽车类型
AbsCar absCar = new SuvCar();
absCar.setBrandProducer(nissanProducer);
// 组装标配车型
absCar.constructBasicCar();
System.out.println("\n****************************************");
// 组装中配车型
absCar.constructMiddleCar();
}