桥接模式属于结构型模式,主要解决因业务增长时滥用继承而导致的**“类爆炸”问题。桥接模式将一个树型的整体继承结构替换为由抽象的类(抽象化角色)组成的抽象部分和由实现接口(实现化角色)与实现类(具体实现化角色)组成的实现部分**,再让较为抽象的类中持有实现接口的实例,以此作为桥梁来完成两个部分的通信。此时,通过将继承关系替换成关联关系实现了抽象类部分与实现类部分的分离与解耦,使得二者可以独立变化。
桥接模式通过将抽象部分与实现部分抽离,使二者的关系有继承转变为聚合关联关系,以此来减少耦合性,让二者能够独立变化与扩展。
这里的抽象与实现并不特指abstract
和implements
,更多是现实生活中所认知的事物。例如:相对一部折叠式的华为手机来说,手机这个类就显得抽象得多,所以可以把手机看做抽象部分,折叠式华为手机看做实现部分。
使用桥接模式可以让抽象和实现不再在同一个继承层次结构中,而是按照事物的多维度变化分成多个部分,而每个部分也需要“子类化”,不论抽象部分还是实现部分,都应当具有自己的子类,以便各个部分的子类随意组合,从而获得多维度的组合对象。
一个事物通常有多个维度,例如,图形从形状上可分为圆形、方形等形状,从颜色角度看有红色、蓝色等。如要把图形按继承的方法抽象成类,那么圆形、方形继承与图形,而圆形又有红色的圆、蓝色的圆等多个子类。
此时我要增加一个三角形,那同时也得增加红色三角形和蓝色三角形,假如我还想再增加一个绿颜色,那么所有图形都得再增加一个绿色的子类。之后当图形和颜色越加越多时,那这个结构中的类就会成指数的增长,导致**“类爆炸”**。
以上面的图形例子来讲,我找到了两个变化的维度,一个是图形会增加,一个是颜色会增加。那么按照桥接模式,可以将颜色这个实现部分抽离出来,实现一个颜色接口,并在图形类中加入一个颜色的实例,以此完成颜色与图形的搭桥连接。
图形颜色
package 设计模式.结构型模式.桥接模式;
/**
* 实现化角色,每个实现类都通过该接口与抽象化相连接
*/
public interface 图形颜色 {
String 上色();
}
红色
package 设计模式.结构型模式.桥接模式;
/**
* 具体实现类
*/
public class 红色 implements 图形颜色 {
@Override
public String 上色() {
return "红色";
}
}
蓝色
package 设计模式.结构型模式.桥接模式;
/**
* 具体实现类
*/
public class 蓝色 implements 图形颜色 {
@Override
public String 上色() {
return "蓝色";
}
}
图形
package 设计模式.结构型模式.桥接模式;
/**
* 抽象化角色
*/
public abstract class 图形 {
// 维护一个实现化的对象
protected 图形颜色 颜色;
protected 图形(图形颜色 颜色){
// 通过构造方法注入实现类过程就是桥接的过程
this.颜色 = 颜色;
}
public abstract void 绘制();
}
圆形
package 设计模式.结构型模式.桥接模式;
public class 圆形 extends 图形 {
// 通过构造方法传递具体的实现类对象,由抽象类保存维护
protected 圆形(图形颜色 颜色) {
super(颜色);
}
@Override
public void 绘制() {
// 在此方法中调用实现类,进行多维组合
System.out.println("绘制一个圆形,并开始上色:"+颜色.上色());
}
}
方形
package 设计模式.结构型模式.桥接模式;
public class 方形 extends 图形 {
// 通过构造方法传递具体的实现类对象,由抽象类保存维护
protected 方形(图形颜色 颜色) {
super(颜色);
}
@Override
public void 绘制() {
// 在此方法中调用实现类,进行多维组合
System.out.println("绘制一个正方形,并且开始上色:"+颜色.上色());
}
}
测试类
package 设计模式.结构型模式.桥接模式;
public class 测试类 {
public static void main(String[] args) {
圆形 红色圆形 = new 圆形(new 红色());
红色圆形.绘制();
方形 蓝色方形 = new 方形(new 蓝色());
蓝色方形.绘制();
圆形 蓝色圆形 = new 圆形(new 蓝色());
蓝色圆形.绘制();
方形 红色方形 = new 方形(new 红色());
红色方形.绘制();
}
}
测试结果