桥接模式概述
桥接(Bridge)是用于把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
代码示例
package com.xnn.eg3;
/**
*
* 类(接口)描述:汽车引擎的接口:
* @author xnn
* 2018年11月4日下午8:45:28
*/
public interface Engine {
//安装引擎
public void installEngine();
}
package com.xnn.eg3;
/**
*
* 类(接口)描述:2000cc的引擎类 实现引擎接口
* @author xnn
* 2018年11月4日下午8:46:16
*/
public class Engine2000 implements Engine {
public void installEngine() {
System.out.println("安装2000cc发动机");
}
}
package com.xnn.eg3;
/**
*
* 类(接口)描述:2200cc的引擎类 实现引擎接口
* @author xnn
* 2018年11月4日下午8:47:14
*/
public class Engine2200 implements Engine{
public void installEngine() {
System.out.println("安装2200cc发动机");
}
}
package com.xnn.eg3;
/**
*
* 类(接口)描述:汽车抽象类
* @author xnn
* 2018年11月4日下午8:44:02
*/
public abstract class Car {
//汽车的引擎
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
public Engine getEngine() {
return engine;
}
public void setEngine(Engine engine) {
this.engine = engine;
}
//给汽车装引擎
public abstract void installEngine();
}
package com.xnn.eg3;
/**
*
* 类(接口)描述:巴士类 继承Car
* @author xnn
* 2018年11月4日下午8:47:59
*/
public class Bus extends Car{
//有参构造函数(传了个引擎进去)
public Bus(Engine engine) {
super(engine);
}
//安装引擎的方法(调用的是Engine类的installEngine()方法)
public void installEngine() {
System.out.print("Bus:");
this.getEngine().installEngine();
}
}
package com.xnn.eg3;
/**
*
* 类(接口)描述:Jeep类 继承Car
* @author xnn
* 2018年11月4日下午8:50:47
*/
public class Jeep extends Car {
public Jeep(Engine engine) {
super(engine);
}
public void installEngine() {
System.out.print("Jeep:");
this.getEngine().installEngine();
}
}
package com.xnn.eg3;
public class MainClass {
public static void main(String[] args) {
Engine engine2000 = new Engine2000();
Engine engine2200 = new Engine2200();
Car car1 = new Bus(engine2000);
car1.installEngine();
Car car2 = new Bus(engine2200);
car2.installEngine();
Car jeep1 = new Jeep(engine2000);
jeep1.installEngine();
Car jeep2 = new Jeep(engine2200);
jeep2.installEngine();
}
}
桥接模式所画出来的的类图
结果:
Bus:安装2000cc发动机
Bus:安装2200cc发动机
Jeep:安装2000cc发动机
Jeep:安装2200cc发动机
用继承来实现的代码体现
package com.xnn.eg1;
/*
* 汽车
*/
public interface Car {
public void installEngine();
}
package com.xnn.eg1;
public abstract class Bus implements Car {
public abstract void installEngine();
}
package com.xnn.eg1;
import com.xnn.eg1.Bus;
public class Bus2000 extends Bus{
public void installEngine() {
System.out.println("给Bus安装2000cc发动机");
}
}
package com.xnn.eg1;
import com.xnn.eg1.Bus;
public class Bus2200 extends Bus {
public void installEngine() {
System.out.println("给Bus安装2200cc发动机");
}
}
package com.xnn.eg1;
public abstract class Jeep implements Car {
public abstract void installEngine();
}
package com.xnn.eg1;
public class Jeep2000 extends Jeep{
public void installEngine() {
System.out.println("给Jeep安装2000cc发动机");
}
}
package com.xnn.eg1;
public class Jeep2200 extends Jeep {
public void installEngine() {
System.out.println("给Jeep安装2200cc发动机");
}
}
package com.xnn.eg1;
public class MainClass {
public static void main(String[] args) {
Car car1 = new Bus2000();
car1.installEngine();
}
}
继承方式实现所画出来的类图
结果:
给Bus安装2000cc发动机
总结
模式意图
将抽象部分与实现部分分离,使它们都可以独立的变化。就上面的例子来说:抽象部分就是汽车及其子类,实现部分就是Engine接口及其实现类。
主要解决的问题
在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。就上面的例子来说,如果用继承实现,那么若系统中新增加了一款车(桑塔纳) 那就需要写一个Santana类实现Car接口,并且还得添加Santana2000、Santana2200这些具体的类继承Santana;若是增加了一款新式引擎,那么还得增添Bus Jeep 的另一个实现类,也就是说系统每新增一款引擎,之前的所有不同品牌的车都得新增一个装这个引擎的不同品牌车的类;
而用桥接模式则是把这两个维度完全分开,品牌不同的车的类全继承Car这个抽象类(体现了抽象类是属性的抽象),而不同引擎的类则实现Engine这个接口(接口体现的是行为的抽象),并且实现里面的“安装引擎”方法。这两个体系(Car抽象类的这个体系和Engin接口的这个体系)通过一个“桥”连接起来(这个桥正是Car类里面的成员属性:engine)
何时使用
实现系统可能有多个角度分类(汽车品牌有分类,引擎有分类),每一种角度都可能变化(自由组合)。
如何解决
把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
关键代码
抽象类依赖实现类。(在抽象类里面注入了接口的实现类对象作为抽象类的属性:即在Car类中有private Engine engine;这个属性)
优点:
1、抽象和实现的分离;
2、优秀的扩展能力;
3、实现细节对客户透明。
缺点
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
使用场景
1、如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。2、对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
3、一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
注意事项
对于两个独立变化的维度,使用桥接模式再适合不过了。
扩展
JDBC的实现也遵循这个模式。