背景: 在一个有多种可能会变化的维度的系统中,用继承的方式会造成类爆炸,扩展起来不灵活。每次在一个维度上新增一个具体的实现都要增加很多的类。比如如下设计的类图:
当采用此种设计时,我们需要不同的形状,就需要继承Shape类来实现不同的形状,当我们需要实现不同颜色的不同形状时,我们需要同样需要继承不同的形状的类,这样就出现了类爆炸的问题。为了更灵活的设计系统,我们此时可以考虑使用桥接模式。在后边的案例中,我们会使用桥接模式将这个问题重写遍,供参考。
定义:将抽象与实现分离,使他们可以独立变化。它使用组合关系代替继承关系来实现的,从而降低了抽象与现实这两个维度的耦合度,也体现了设计原则中的【合成复用】与【依赖倒转】原则,还包括【开闭原则】。
传送门:面向对象软件设计原则【JAVA】(开闭原则、里氏代换、依赖倒转、接口隔离、迪米特法则、合成复用原则)
桥接模式包含以下主要角色:
通过观察背景案例,我们发现可以将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());
}
}