什么意思呢,先来看段简单代码
// 父类
public abstract class Father {
// 父类的普通功能
public void method1() {
// doSomething
}
// 父类的抽象方法
public abstract void method2();
}
// 子类A
public class SonA extends Father {
// 实现父类方法
public void method2() {
// doSomething
}
}
public class SonB extends Father {
// 实现父类方法
public void method2() {
// doSomething
}
// 增加父类没有的方法
public void method3() {
// doSomething
}
}
在父类中通过声明抽象方法来定义接口(API),子类通过实现具体方法来实现接口(API),这种层次结构被称为类的实现层次结构,比如Father有抽象方法method2(),子类都实现了method2(),那么Father和两个实现类SonA、SonB都具有类的实现层次结构,Father处于最顶层。
在父类中具有基本功能,在子类中增加新的功能,这种层次结构被称为类的功能层次结构,比如Father具有基本功能方法method1(),而子类SonB除了继承自父类的method1(),还扩展增加了method3(),所以Father和SonB具有类的功能层次结构,同样Father处于最顶层。
如图:

当类的层次结构只有一层时,功能层次结构与实现层次结构是混杂在一个层次结构中的。这样很容易使类的层次结构变得复杂, 也难以透彻地理解类的层次结构,因为自己难以确定究竟应该在类的哪个层次结构去增加子类。因此我们需要将“类的功能层次结构”和”类的实现层次结构“分离为两个独立的类层次结构,并在它们之间搭建一座桥梁,Bridge模式的作用就是搭建这座桥梁。
怎么分离呢?先看一下,上面的例子是使用”继承“来扩展类的,但是类之间也形成了一种强关联关系。这时,我们可以使用”委托“来代替“继承”关系。
再来看个例子,我们需要实现“显示一些东西”这个功能。
Display类的功能是抽象的,负责“显示一些东西”,该类位于“类的功能层次结构”的最上层。在impl字段中保存的是实现了Display类的具体功能的实例,即是类的两个层次结构的“桥梁”。
public class Display {
private DisplayImpl impl;
public Display(DisplayImpl rawDisplay) {
this.impl = rawDisplay;
}
public void open() {
impl.rawOpen();
}
public void print() {
impl.rawPrint();
}
public void close() {
impl.rawClose();
}
public void display() {
open();
print();
close();
}
}
CountDisplay类在Display类的基础上增加了一个新功能,所以它也属于“类的功能层次结构”。
public class CountDisplay extends Display {
public CountDisplay(DisplayImpl rawDisplay) {
super(rawDisplay);
}
public void mutiDisplay(int times) {
open();
for (int i = 0; i < times; i++) {
print();
}
close();
}
}
DisplayImpl类位于“类的实现层次结构”的最上层,它是一个抽象类,里面的方法与Display的抽象功能方法一一对应,进行显示前、显示、显示后的处理,但是具体的实现交给子类。
public abstract class DisplayImpl {
public abstract void rawOpen();
public abstract void rawPrint();
public abstract void rawClose();
}
StringDisplayImpl类是真正的“实现”,继承自DisplayImpl并实现其抽象方法,同样作为”类的实现层次结构“的一员。
public class StringDisplayImpl extends DisplayImpl {
private String string;
private int width;
public StringDisplayImpl(String string) {
this.string = string;
this.width = string.getBytes().length;
}
@Override
public void rawOpen() {
printLine();
}
@Override
public void rawPrint() {
System.out.println("|" + string + "|");
}
@Override
public void rawClose() {
printLine();
}
private void printLine() {
System.out.print("+");
for (int i = 0; i < width; i++) {
System.out.print("-");
}
System.out.println("+");
}
}
测试方法
public class Test {
public static void main(String[] args) {
Display d1 = new Display(new StringDisplayImpl("Hello, China."));
Display d2 = new CountDisplay(new StringDisplayImpl("Hello, World."));
CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hello, Universe."));
d1.display();
d2.display();
d3.display();
d3.mutiDisplay(5);
}
}
我的理解是,将两种类的层次结构进行分离,弱化类之间的关联关系,这样就可以明确,当我们要增加新功能时,只在”类的功能层次结构“上进行调整,如增加一个类似于CountDisplay的新类继承于Display,然后增加新方法。又或者当我们想要对已有的抽象方法增加新的实现时,只需要增加一个类似于StringDisplay的新类,由它去完成对DisplayImpl中抽象方法的不同实现。
