1.定义
背景: 在一个有多种可能会变化的维度的系统中,用继承的方式会造成类爆炸,扩展起来不灵活。每次在一个维度上新增一个具体的实现都要增加很多的类。比如如下设计的类图:
当采用此种设计时,我们需要不同的形状,就需要继承Shape类来实现不同的形状,当我们需要实现不同颜色的不同形状时,我们需要同样需要继承不同的形状的类,这样就出现了类爆炸的问题。为了更灵活的设计系统,我们此时可以考虑使用桥接模式。在后边的案例中,我们会使用桥接模式将这个问题重写遍,供参考。
定义:将抽象与实现分离,使他们可以独立变化。它使用组合关系代替继承关系来实现的,从而降低了抽象与现实这两个维度的耦合度,也体现了设计原则中的【合成复用】与【依赖倒转】原则,还包括【开闭原则】。
传送门:面向对象软件设计原则【JAVA】(开闭原则、里氏代换、依赖倒转、接口隔离、迪米特法则、合成复用原则)
2.结构
桥接模式包含以下主要角色:
- 抽象化角色:定义抽象类,并包含一个对实现化对象的引用。
- 扩展抽象化角色:是抽象化角色的子类,实现父类中的业务方法,并通过组合关系调用实现化角色中的业务方法。
- 实现化角色:定义实现化角色的接口,供扩展抽象化角色调用。
- 具体实现化角色:给出实现化角色接口的具体实现。
3.背景案例改写
通过观察背景案例,我们发现可以将Shape
与color
这两种可能会变化的维度,单独分离出来,采用桥接模式,用组合关系代替继承关系来实现。其类图如下所示:
可以看到我们将Shape与Color进行了分离,Shape采用了抽象类实现,Color采用了接口方式实现,Shape与Color为组合关系,Shape与Color可以独自发展,并不会出现案例所说的情况,当我们需要别的颜色的时候我们只需要实现Color接口即可,当我们实现其他的形状的时候就可以通过继承Shape来实现。所谓桥接,感觉就是,将原本在将类堆在一起的设计方式,按照某几个维度分离,并通过组合的方式进行连接,这样可以提高系统的可扩展性,在分离出的变化维度中任意扩展一个维度,都不需要修改原有的系统。
案例的实现代码如下:
abstract class Shape {
protected Color color;
public Shape(Color color) {
this.color = color;
}
public abstract String PrintShape();
}
class Circle extends Shape{
public Circle(Color color) {
super(color);
}
@Override
public String PrintShape() {
return color.getColor() + " Circle";
}
}
class Rectangle extends Shape{
public Rectangle(Color color) {
super(color);
}
@Override
public String PrintShape() {
return color.getColor() + " Rectangle";
}
}
interface Color {
abstract String getColor();
}
class Green implements Color{
@Override
public String getColor() {
return "Green";
}
}
class Red implements Color{
@Override
public String getColor() {
return "Red";
}
}
public class Client {
public static void main(String[] args) {
Shape circle = new Circle(new Green());
System.out.println(circle.PrintShape());
Shape rectangle = new Rectangle(new Red());
System.out.println(rectangle.PrintShape());
}
}
4.优点
- 桥接模式提高了系统的可扩展性,在分离出的变化维度中任意扩展一个维度,都不要修改原有系统。
- 实现细节对客户透明。
5.使用场景
- 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
- 当一个系统不希望使用继承或者因为多层次继承导致系统类的个数急剧增加时。
- 当一个系统需要在构件的抽象化角色和具体角色之间增加更多的灵活性时。避免在两个层次之间建立静态的继承关系,通过桥接模式可以使他们在抽象层建立一个关联关系。
文章评论