软件设计模式 | 结构型之桥接模式详解
桥接模式引述
我们先举一个生活中的小例子,比如:画图。
这里有一个画笔, 可以画三种图形分别是:正方形,三角形,圆形。然后还需要给这些形状上色,这里有红、黄、蓝三种颜色。那么我们可以有 3*3 一共 9 种组合。这里呢,存在两种解决方案:
1. 方案一:为每种形状都提供各种颜色的版本。
2. 方案二:根据实际需要对颜色和形状进行组合。
-
如果采用方案一来实现,那么实现效果如图所示:

形状与颜色少的情况下完全可以的,我们可以理解成每一种颜色都提供了各种形状的版本。那么假如要增加一个绿色,那么以上三种图形的颜色都要新增。随着颜色或者形状的新增,那么这种解决方案早晚会 爆炸,所以方案一不可取! -
那么我们采用方案二看一下,方案二所提供的解决方案就是:提供两个父类,分别是颜色和形状。二者都包含相应的字类,然后根据颜色和形状进行组合,实现效果如图:

对于有几个变化的维度,我们一般采用方案二来实现,这样除了减少系统中的类个数,也利于系统扩展。对于方案二的应用我们称之为桥接模式。
一、模式介绍
桥接(Bridge)是用于 把抽象化与实现化解耦,使得二者可以独立变化。这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
这种模式涉及到一个作为桥接的接口,使得实体类的功能独立于接口实现类。这两种类型的类可被结构化改变而互不影响。
二、模式结构
模板类图如下:

桥接模式主要包含如下几个角色:
- Abstraction:抽象类
- RefinedAbstraction:扩充抽象类
- Implementor:实现类接口
- ConcreteImplementor:具体实现类
注意:这里对于抽象类和实现类接口的选取没有做实际的区分,比如本篇文章的例题既可以选取形状作为抽象类颜色作为实现类接口,也可以选取颜色作为实现类形状作为抽象类的接口。但是我们一般将与客户直接访问的类作为抽象类,或者说是二个维度之间比较重要的那一类作为抽象类。
拿本道例题举例,一般会先选形状再选颜色,所以可以把形状作为抽象类,但是选取颜色为抽象类也是可以的。
三、模式实现
这里我们通过以下两道题目进行练习桥接模式。
3.1 画图
本篇文章的例题:这里有一个画笔, 可以画三种图形分别是:正方形,三角形,圆形。然后还需要给这些形状上色,这里有红、黄、蓝三种颜色,使用适桥接模式进行系统设计。绘制类图并编程模拟实现。
类图如下:

代码如下:
Shape : (Abstraction)抽象类
public abstract class Shape {
Color color;
public void setColor(Color color){
this.color = color;
}
public abstract void draw();
}
RefinedAbstraction:扩充抽象类,包括:正方形、三角形、圆形
public class Square extends Shape {
@Override
public void draw() {
color.bePaint("正方形");
}
}
public class Triangle extends Shape {
@Override
public void draw() {
color.bePaint("三角形");
}
}
public class Circle extends Shape {
@Override
public void draw() {
color.bePaint("圆形");
}
}
Color : (Implementor)实现类接口
public interface Color {
public void bePaint(String shape);
}
ConcreteImplementor: 具体实现类,包括:红色、黄色、蓝色
public class Red implements Color {
@Override
public void bePaint(String shape) {
System.out.println("红色的"+shape);
}
}
public class Yellow implements Color {
@Override
public void bePaint(String shape) {
System.out.println("白色的"+shape);
}
}
public class Blue implements Color {
@Override
public void bePaint(String shape) {
System.out.println("绿色的"+shape);
}
}
客户端代码演示:
public class Client {
public static void main(String[] args) {
Color yellow = new Yellow();//黄色
Shape square = new Square();//正方形
square.setColor(yellow);
square.draw();
Color blue = new Blue();//蓝色
Shape triangle = new Triangle();//三角形
triangle.setColor(blue);
triangle.draw();
}
}
结果展示:

3.2 汽车的品牌与变速器
汽车可按品牌分为宝马、奔驰、路虎(BMW、BenZ、LandRover),也按自动挡、手动挡与手自一体(Auto、Manual、AMTY)分类,使用适桥接模式进行系统设计。绘制类图并编程模拟实现。
类图如下:

Car : (Abstraction)抽象类
public abstract class Car {
public Transmission transmission;
public void setTransmission(Transmission transmission) {
this.transmission = transmission;
}
public abstract void run();
}
RefinedAbstraction:扩充抽象类,包括:BMW、Benz、LandRover
public class BMW extends Car {
@Override
public void run() {
transmission.gear();
System.out.println("宝马");
}
}
public class Benz extends Car {
@Override
public void run() {
transmission.gear();
System.out.println("奔驰");
}
}
public class LandRover extends Car {
@Override
public void run() {
transmission.gear();
System.out.println("路虎");
}
}
Color : (Implementor)实现类接口
public interface Transmission{
public void gear();
}
ConcreteImplementor: 具体实现类,包括:Auto、Manual、AMT
public class Auto implements Transmission {
@Override
public void gear() {
System.out.print("自动档的");
}
}
public class Manual implements Transmission {
@Override
public void gear() {
System.out.print("手动档的");
}
}
public class AMT implements Transmission{
@Override
public void gear() {
System.out.print("手自一体的");
}
}
客户端代码演示:
public class Client {
public static void main(String[] args) {
Transmission auto = new Auto();//自动档
Car bmw = new BMW();//宝马
bmw.setTransmission(auto);
bmw.run();
Transmission manual = new Manual();//手动档
Car benz = new Benz();//奔驰
benz.setTransmission(manual);
benz.run();
}
}
结果展示:

四、模式优缺点
优点:
- 分离抽象接口及其实现部分。提高了比继承更好的解决方案。
- 桥接模式提高了系统的可扩充性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统。
- 实现细节对客户透明,可以对用户隐藏实现细节。
缺点
- 桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
- 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性。
五、 模式使用场景
- 如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
- 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
- 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
六、 模式总结
- 桥接模式实现了抽象化与实现化的脱耦。他们两个互相独立,不会影响到对方。
- 对于两个独立变化的维度,使用桥接模式再适合不过了。
- 对于"具体的抽象类"所做的改变,是不会影响到客户。
更多推荐


所有评论(0)