Bridge的意思是“桥梁”。就像在现实世界中,桥梁的功能是将河流的两侧连接起来一样,Bridge模式的作用也是将两样东西连接起来,它们分别是类的功能层次结构和类的实现层次结构。
类的层次结构的两个作用
希望增加新功能时: (1)父类具有基本功能 (2)在子类中增加新功能 这种层次结构被称为“类的功能层次结构”。
希望增加新实现时: (1)父类通过声明抽象方法来定义接口(API) (2)子类通过实现具体方法来实现接口(API) 这种层次结构被称为“类的实现层次结构”。
桥接模式简介
(1)桥接(Bridge)模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。又称为柄体(Handle and Body)模式或接口(Interface)模式。 (2)分类:结构型模式。通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。 (3)意图:将抽象部分与实现部分分离,使它们都可以独立的变化。
(4)主要解决:在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
(5)何时使用:实现系统可能有多个角度分类,每一种角度都可能变化。
(6)如何解决:把这种多角度分类分离出来,让它们独立变化,减少它们之间耦合。
角色结构
抽象化(Abstraction)角色:用于定义抽象类的接口,它一般是抽象类而不是接口。 修正抽象化(RefinedAbstraction)角色:扩展抽象化角色,改变和修正父类对抽象化的定义。 实现者(Implementor)角色:定义实现类的接口,一般而言,Implementor接口仅提供基本操作,而Abstraction定义的接口可能会做更多更复杂的操作。Implementor接口对这些基本操作进行了声明,而具体实现交给其子类。通过关联关系,在Abstraction中不仅拥有自己的方法,还可以调用到Implementor中定义的方法,使用关联关系来替代继承关系。 具体实现者(ConcreteImplementor)角色:具体实现Implementor接口。
具体实现
使用相同的抽象类方法但是不同的桥接实现类,来画出不同颜色的圆。
步骤一:创建桥接实现接口。
/**
* 创建桥接实现接口
* @author Administrator
*
*/
public interface IDrawAPI {
void drawCircle(
int radius,
int x,
int y);
}
步骤二:创建实现了 DrawAPI 接口的实体桥接实现类。
/**
* 创建实现了 DrawAPI 接口的实体桥接实现类。
* @author Administrator
*
*/
public class RedCircle implements IDrawAPI {
@Override
public void drawCircle(
int radius,
int x,
int y) {
System.out.println(
"Drawing Circle[ color: red, radius: "
+ radius +
", x: " +x+
", "+ y +
"]");
}
}
/**
* 创建实现了 DrawAPI 接口的实体桥接实现类。
* @author Administrator
*
*/
public class GreenCircle implements IDrawAPI {
@Override
public void drawCircle(
int radius,
int x,
int y) {
System.out.println(
"Drawing Circle[ color: green, radius: "
+ radius +
", x: " +x+
", "+ y +
"]");
}
}
步骤三:使用 DrawAPI 接口创建抽象类 Shape。
/**
* 使用 DrawAPI 接口创建抽象类 Shape。
* @author Administrator
*
*/
public abstract class Shape {
protected IDrawAPI drawAPI;
protected Shape(IDrawAPI drawAPI){
this.drawAPI = drawAPI;
}
public abstract void draw();
}
步骤四:创建实现了 Shape 接口的实体类。
/**
* 创建实现了 Shape 接口的实体类。
* @author Administrator
*
*/
public class Circle extends Shape {
private int x, y, radius;
public Circle(
int x,
int y,
int radius, IDrawAPI drawAPI) {
super(drawAPI);
this.x = x;
this.y = y;
this.radius = radius;
}
public void draw() {
drawAPI.drawCircle(radius,x,y);
}
}
步骤五:使用 Shape 和 DrawAPI 类画出不同颜色的圆。
/**
* 使用 Shape 和 DrawAPI 类画出不同颜色的圆。
* @author Administrator
*
*/
public class BridgePatternDemo {
public static void main(String[] args) {
Shape redCircle =
new Circle(
100,
100,
10,
new RedCircle());
Shape greenCircle =
new Circle(
100,
100,
10,
new GreenCircle());
redCircle.draw();
greenCircle.draw();
}
}
步骤六:验证结果。
Drawing
Circle[ color: red, radius: 10, x: 100, 100]
Drawing
Circle[ color: green, radius: 10, x: 100, 100]
总结
关键代码:抽象类依赖实现类。
应用实例:
猪八戒从天蓬元帅转世投胎到猪,转世投胎的机制将尘世划分为两个等级,即:灵魂和肉体,前者相当于抽象化,后者相当于实现化。生灵通过功能的委派,调用肉体对象的功能,使得生灵可以动态地选择。墙上的开关,可以看到的开关是抽象的,不用管里面具体怎么实现的。
优点:
抽象和实现的分离。 优秀的扩展能力。 实现细节对客户透明。
缺点:桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。
使用场景:
如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。 对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。 一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
注意事项:对于两个独立变化的维度,使用桥接模式再适合不过了。