桥接模式

桥接模式

桥接模式(Bridge Pattern) 也称为桥梁模式、接口模式或者柄体模式,是将抽象部分与它的具体实现部分分离,使它们都可以独立地变化,属于结构型模式。桥接模式主要目的是通过组合的方式建立两个类之间的联系,而不是继承。但又类似于多重继承方案,但是多重继承方案往往违背了类的单一职责原则,其复用性较差,桥接模式是比多重继承更好的替代方案。桥接模式的核心在于解耦抽象和实现。

桥接模式的一个常用场景就是为了替换继承。继承有很多优点,比如抽象,封装,多态等,父类封装共性,子类实现特性。继承可以很好地帮助我们实现代码复用(封装)的功能,但是同时,这也是继承的一大缺点。因为父类拥有的方法,子类也会继承得到,无论子类是否需要。这说明了继承具备强侵入性(父类代码侵入子类),同时会导致子类臃肿。因此,在设计模式中,有一个原则为,优先使用组合/聚合的方式,而不是继承。

应用场景

当一个类内部具备两种或多种变化维度时,使用桥接模式可以解耦这些变化的维度,使高层代码架构稳定。

桥接模式适用于以下几种业务场景:

  • 在抽象和具体实现之间需要增加更多的灵活性的场景

  • 一个类存在两个或多个独立变化的维度,而这两个或多个维度都需要独立进行扩展

  • 不希望使用继承,或因为多层继承导致系统类的个数剧增

桥接模式的角色组成

抽象(Abstraction): 该类持有一个对实现角色的引用,抽象角色中的方法需要实现角色来实现,抽象角色一般为抽象类(构造函数规定子类要传入一个实现对象);
修正抽象(RefinedAbstraction): Abstraction的具体实现,对Abstraction的方法进行完善和扩展;
实现(Implementor): 确定实现维度的基本操作,提供给Abstraction使用。该类一般为接口或者抽象类;
具体实现(ConcreteImplementor): Implementor的具体实现;

例子

image-20231229143142802

抽象:包含一个实现的引用

1
2
3
4
5
6
7
8
9
10
public abstract class Image {
ImageImp imageImp;

public void setImageImp(ImageImp imageImp){
this.imageImp = imageImp;
}

public abstract void parseFile(String fileName);

}

修正抽象

1
2
3
4
5
6
7
8
9
public class PNGImage extends Image{
@Override
public void parseFile(String fileName) {
//模拟解析PNG文件并获得一个像素矩阵对象
Matrix m = new Matrix();
imageImp.doPaint(m);
System.out.println(fileName+"格式为PNG");
}
}
1
2
3
4
5
6
7
8
9
10
public class GIFImage extends Image{
@Override
public void parseFile(String fileName) {
//模拟解析GIF文件并获得一个像素矩阵对象
Matrix m = new Matrix();
imageImp.doPaint(m);
System.out.println(fileName+"格式为GIF");
}
}

1
2
3
public class Matrix {
//代码省略
}

抽象实现

1
2
3
4
public interface ImageImp {
public void doPaint(Matrix m);
}

具体实现

1
2
3
4
5
6
public class UnixImp implements ImageImp{
@Override
public void doPaint(Matrix m) {
System.out.println("在Unix上显示图像:");
}
}
1
2
3
4
5
6
7
public class WindowsImp implements ImageImp {
@Override
public void doPaint(Matrix m) {
System.out.println("在windows上显示图形:");
}
}

客户端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Client {
public static void main(String[] args) {
Image gifImage = new GIFImage();
Image pngImage = new PNGImage();
ImageImp unixImp = new UnixImp();
ImageImp winImp = new WindowsImp();

gifImage.setImageImp(unixImp);
gifImage.parseFile("小龙女");
pngImage.setImageImp(winImp);
pngImage.parseFile("杨过");
}
}

image-20231229144614892

优点:

  • 分离抽象接口及其实现部分。使得抽象和实现可以沿着各自的维度来变化,也就是说抽象和实现不再在同一个继承层次结构中,而是“子类化”它们,使它们各自都具有自己的子类,以便任何组合子类,从而获得多维度组合对象。

  • 在很多情况下,桥接模式可以取代多层继承方案,多层继承方案违背了“单一职责原则”,复用性较差,且类的个数非常多,桥接模式是比多层继承方案更好的解决方法,它极大减少了子类的个数。

  • 桥接模式提高了系统的可扩展性,在两个变化维度中任意扩展一个维度,都不需要修改原有系统,符合“开闭原则”。

缺点:

  • 桥接模式的使用会增加系统的理解与设计难度,由于关联关系建立在抽象层,要求开发者一开始就针对抽象层进行设计与编程。
  • 桥接模式要求正确识别出系统中两个独立变化的维度,因此其使用范围具有一定的局限性,如何正确识别两个独立维度也需要一定的经验积累。

桥接模式
http://example.com/2023/10/15/计算机基础/设计模式/10-桥接模式/
作者
PALE13
发布于
2023年10月15日
许可协议