👉文章示例代码👈
定义
将抽象部分与它的具体实现部分分离,使它们都可以独立地变化。
桥接模式是通过组合的方式建立两个类之间的联系,而不是通过继承。
四个角色
桥接模式中主要有以下四个角色:
- 抽象化角色Abstraction:定义抽象类,同时包含一个对实现化对象的引用。
- 扩展抽象化角色Refined Abstraction:抽象化角色的子类,实现父类中的方法,同时通过组合关系调用实现化角色当中的方法。
- 实现化角色Implementor:定义实现类的接口,供扩展抽象化角色调用。
- 具体实现化角色Concrete Implementor:定义实现化角色接口的具体实现。
场景示例
笔者这里用不同的笔(圆珠笔、铅笔)来绘制不同图形(圆形、正方形)来举例。
这里先不引进桥接模式,而是采用继承的方式来实现。
创建抽象类
这里创建一个抽象父类,主要是为了做接口约束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
public abstract class Pen {
private String name;
public Pen(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public abstract void draw(); }
|
创建抽象子类
创建不同笔种的抽象子类,继承抽象父类 Pen
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public abstract class Pencil extends Pen {
public Pencil() { super("铅笔"); } }
public abstract class BallPen extends Pen {
public BallPen() { super("圆珠笔类"); } }
|
创建具体的实现子类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
|
public class CircleWithPencil extends Pencil {
@Override public void draw() { System.out.println(getName() + "画圆"); } }
public class SquareWithPencil extends Pencil {
@Override public void draw() { System.out.println(getName() + "画正方形"); } }
public class CircleWithBallPen extends BallPen {
@Override public void draw() { System.out.println(getName() + "画圆"); } }
public class SquareWithBallPen extends BallPen {
@Override public void draw() { System.out.println(getName() + "画正方形"); } }
|
测试类及输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class Test {
public static void main(String[] args) { Pen circleWithBallPen = new CircleWithBallPen(); circleWithBallPen.draw();
Pen circleWithPencil = new CircleWithPencil(); circleWithPencil.draw();
Pen squareWithBallPen = new SquareWithBallPen(); squareWithBallPen.draw();
Pen squareWithPencil = new SquareWithPencil(); squareWithPencil.draw(); } }
|
测试类的输出结果如下:
圆珠笔类画圆
铅笔画圆
圆珠笔类画正方形
铅笔画正方形
类结构图
以上示例类的结构图如下所示

问题所在
上述代码虽然能满足我们的需求,但是你会发现一个问题。
当我们需要扩展一项内容的时候,比方说,用各种笔来绘制直线图形,那这个时候我们就需要在示例中的抽象子类 Pencil
、 BallPen
当中各自增加 LineWithPencil
类和 LineWithBallPen
类。又或者,我们需要使用彩笔来绘制各种图形,那我们需要新增一个抽象子类 ColourPen
,然后写出其具体子类 CircleWithColourPen
类和 SquareWithColourPen
类。
换句话也就是说,我们在笔和图形这两个维度中任意增加一种情况,就需要增加不同维度数量的类。
延伸到多个维度,这种方式会导致类的成倍的增加,发生类爆炸。同时这种设计也使得程序的代码变得相当的臃肿。可见继承在这种场景中是相当麻烦的。
方案改进
现在引入桥接模式对上述示例进行实现。
通过示例,我们可以简单分析得知,这里变化的主要有两个部分,一个部分是笔的种类,另一个部分则是图形的种类。通过桥接模式,我们把这种多个维度分离出来,让其独立的变化,减少之间的耦合。
创建实现化角色
1 2 3 4 5 6 7 8 9
|
public interface Shape {
String draw(); }
|
创建具体实现化角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public class Circle implements Shape {
public String draw() { return "画圆"; } }
public class Square implements Shape {
public String draw() { return "画正方形"; } }
|
创建抽象化角色
此处抽象化角色通过组合的方式,包含了一个对实现化角色的引用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
public abstract class Pen {
protected Shape shape;
public Pen(Shape shape) { this.shape = shape; }
public abstract void draw(); }
|
创建扩展抽象化角色
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
public class Pencil extends Pen {
public Pencil(Shape shape) { super(shape); }
@Override public void draw() { System.out.println("铅笔" + super.shape.draw()); } }
public class BallPen extends Pen {
public BallPen(Shape shape) { super(shape); }
@Override public void draw() { System.out.println("圆珠笔" + super.shape.draw()); } }
|
测试类及输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
public class Test {
public static void main(String[] args) { Pen ballPen1 = new BallPen(new Circle()); ballPen1.draw();
Pen ballPen2 = new BallPen(new Square()); ballPen2.draw();
Pencil pencil1 = new Pencil(new Circle()); pencil1.draw();
Pencil pencil2 = new Pencil(new Square()); pencil2.draw(); } }
|
测试类的输出结果如下:
圆珠笔画圆
圆珠笔画正方形
铅笔画圆
铅笔画正方形
类结构图
以上示例类的结构图如下所示

通过类图我们可以清楚地看到实现化角色 Shape
和抽象化角色 Pen
之间是一比一的组合关系,两者都可以独立的扩展自己。如论两者如何进行组合,都不会发生类爆炸的情况。
总结
适用场景
- 在抽象部分和具体实现部分之间需要增加更多的灵活性。
- 一个类存在两个(或者多个)独立变化的维度,并且这两个(或者多个)维度都需要独立地进行扩展。
- 由于多层继承导致系统类的个数剧增,或者说不想使用继承。
优点
- 抽象部分和具体实现部分分离
- 提高了系统的可扩展性
- 避免类爆炸
缺点
- 增加了系统的理解与设计难度
- 使用范围具有局限性,需要识别出系统中两个独立变化的维度
参考