1. 什么是桥接模式?
桥接模式(Bridge Pattern):将抽象部分与他的实现部分分离,使他们都可以独自变化。桥接模式是一种对象结构型模式。
对于有两个或多个变化维度(即多个变化的原因)时,将每个维度分离开并采用相互组合的方式可以减少类与类之间的耦合,同时有利于扩展,这种方式就是桥接模式。对于定义中的抽象与实现分离开可以理解为将维度与维度分离开,使之单独变化,互不影响。
维度,又称维数,是数学中独立参数的数目。在物理学和哲学的领域内,指独立的时空坐标的数目。此处指独立变化的参数数目,独立变化的原因。
为了加深理解,举个例子:
例如当需要绘制矩形、圆形、三角形、菱形四种形状,且每种形状又有红、黄、蓝、紫四种不同的颜色,如果采用多继承的方式来实现的话,至少需要4*4=16个类(忽略抽象父类或接口),比如红矩形、黄矩形、绿矩形...。如果采用桥接模式,将图形和颜色分离开来,通过组合的方式实现的话,就只需要4+4=8个类(忽略抽象父类或接口),而且最重要的是对于图形和颜色的扩展相当方便。当维度数量越多时,桥接模式的优势越明显。此处的图形和颜色就是两个变化的维度,当单独分离开后就可以相互组合了。
2. 角色
图片来源于网络
公共抽象类(Abstraction):此类定义公共的抽象方法,且有一个Implementor的引用。Abstraction的子类需要完善父类的方法,并且可以调用Implementor的方法来扩展父类的功能。
抽象类具体实现类(RefinedAbstraction):是Abstraction的具体实现,完善并扩展Abstraction的方法。
实现类接口(Implementor):定义了一系列的抽象类的实现方法,需要由子类实现。此类可以是接口或抽象类。方法可以和抽象类不同。实现类的方法都是为抽象类服务的。
具体实现类(ConcreteImplementor):具体的实现类。
注意:此处不太好理解,什么实现类什么抽象类,容易让人蒙圈。此处可以这样理解,Abstraction和Implementor就是两个不同的维度(不同的变化原因),比如图形和颜色。而RefinedAbstraction就是具体的图形,比如矩形、圆形等;ConcreteImplementor就是具体的颜色,比如红色、黄色等。
3. 优点
(1)将抽象与实现分离,可以复用代码,对于多维度场景可以减少类个数。
(2)通过组合的方式可以使类与类之间解耦。提高了系统的可扩展性,任意一个维度进行扩展都不需要修改原有系统。
(3)桥接模式是多继承场景的更好解决方案。
4. 缺点
(1)桥接模式的引入会增加系统的理解与设计难度。
(2)桥接模式要求正确识别出系统中两个或多个独立变化的维度,因此其使用范围具有一定的局限性。
5. 使用场景
(1)一个类存在两个或多个独立变化的维度,且这些维度都需要进行独立的扩展时可以使用桥接模式。
(2)对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
6. 实例代码
绘制正方形、圆形两种形状,且每种形状又有红黄绿三种不同的颜色。不同的形状就是一种维度,不同的颜色又是另一种维度。
(1)公共抽象类:图形
/**
* 图形公共抽象类
* 具有颜色的引用和一个画图的默认抽象方法
*/
public abstract class Figure {
//颜色引用,每个图形都有一种颜色
private Colour colour;
public Figure(Colour colour) {
this.colour=colour;
}
public void setColour(Colour colour) {
this.colour = colour;
}
public Colour getColour() {
return colour;
}
//绘画图形
public abstract void drew();
}
(2)实现类公共接口:颜色
/**
* 颜色接口
*/
public interface Colour {
//给物体上色方法
public void pigment();
}
(3)抽象类具体实现类
/**
* 正方形
*/
public class Square extends Figure {
public Square(Colour colour) {
super(colour);
}
@Override
public void drew() {
System.out.print("正方形:");
this.getColour().pigment();
}
}
/**
* 圆形
*/
public class Circle extends Figure {
public Circle(Colour colour) {
super(colour);
}
@Override
public void drew() {
System.out.print("圆形:");
this.getColour().pigment();
}
}
(4)具体实现类
public class Red implements Colour {
@Override
public void pigment() {
System.out.println("红色的");
}
}
public class Green implements Colour {
@Override
public void pigment() {
System.out.println("绿色的");
}
}
public class Yellow implements Colour {
@Override
public void pigment() {
System.out.println("黄色的");
}
}
(5)测试
public class Client {
public static void main(String[] args) {
//创建颜色对象
Colour red=new Red();
Colour yellow=new Yellow();
Colour green=new Green();
//画三种颜色的圆形
Figure circle1=new Circle(red);
circle1.drew();
Figure circle2=new Circle(yellow);
circle2.drew();
Figure circle3=new Circle(green);
circle3.drew();
//画三种颜色的正方形
Figure square1=new Square(green);
square1.drew();
Figure square2=new Square(red);
square2.drew();
Figure square3=new Square(yellow);
square3.drew();
}
}
(6)测试结果
圆形:红色的
圆形:黄色的
圆形:绿色的
正方形:绿色的
正方形:红色的
正方形:黄色的