《设计模式:可复用软件对象软件的基础》的阅读笔记 -第二章 桥接模式

2.6.2 封装实现依赖关系

在这一节中,作者探讨了如何在支持多种窗口系统时,封装实现依赖关系,以避免应用程序代码与具体窗口系统实现之间的紧密耦合。

主要问题

当开发一个跨平台的应用程序时,通常需要支持多种窗口系统(如Windows、Mac OS等)。如果直接在应用程序代码中使用具体的窗口系统类,会导致代码难以维护和扩展。例如,如果需要添加对新的窗口系统支持,就需要修改大量代码

解决方案:使用桥接模式(Bridge Pattern)

桥接模式是一种结构型设计模式,用于将抽象与实现解耦,使它们可以独立变化。具体来说,桥接模式通过一个“桥接类”将抽象接口与具体实现分离开来
  • 抽象接口:定义一个抽象类(如Window),它包含指向具体实现类的引用。这个抽象类提供了应用程序需要的所有接口方法。
  • 具体实现类:定义一个实现类层次结构(如WindowImp),它包含了具体窗口系统的实现细节
  • 桥接类:通过在抽象类中包含一个指向具体实现类的引用,应用程序代码可以调用抽象类的方法,而这些方法会委托给具体实现类

window基类的构造器使用WindowSystemFactory接口来获得合适的WindowImp。

优点

  • 解耦:应用程序代码与具体窗口系统的实现解耦,便于维护和扩展
  • 灵活性:可以独立地修改抽象接口和具体实现
  • 可扩展性:新增窗口系统时,只需添加新的具体实现类,无需修改现有代码
通过桥接模式,应用程序可以灵活地支持多种窗口系统,同时保持代码的清晰和可维护。

桥接模式和抽象工厂模式的区别

桥接模式和抽象工厂模式都是设计模式中的重要模式,它们在目的、结构和适用场景上存在明显的区别

目的

  • 桥接模式:将抽象与实现解耦,使它们可以独立变化。其目的是分离抽象部分与实现部分,让它们可以独立地变化,从而提高系统的灵活性和可扩展性。
  • 抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们的具体类。其目的是创建一组相关的产品对象,而不需要明确指定具体类,使得客户端代码与具体产品类解耦。

结构

  • 桥接模式:
    • 抽象部分(Abstraction):定义高层控制逻辑,并维护对实现部分的引用。
    • 实现部分(Implementor):定义实现类的接口,提供基本操作的接口。
    • 具体实现(Concrete Implementor):实现Implementor接口,提供具体的实现。
    • 修正抽象(Refined Abstraction):扩展抽象接口,添加额外的功能。
  • 抽象工厂模式:
    • 抽象工厂(Abstract Factory):声明了一组用于创建产品对象的方法,每个方法对应一种产品类型。
    • 具体工厂(Concrete Factory):实现了抽象工厂接口,负责创建具体产品对象的实例。
    • 抽象产品(Abstract Product):定义了一组产品对象的共同接口或抽象类,描述了产品对象的公共方法。
    • 具体产品(Concrete Product):实现了抽象产品接口,定义了具体产品的特定行为和属性。

适用场景

  • 桥接模式:
    • 当一个类存在两个独立变化的维度,且这两个维度都需要进行扩展时。
    • 当系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性时。
    • 当需要避免使用继承导致的类爆炸问题,提供更灵活的扩展方式时。
  • 抽象工厂模式:
    • 当系统需要创建多个相关或依赖的对象,而不需要指定具体类时。
    • 当客户端需要与多个不同系列的相关产品交互,但不希望代码基于产品的具体类进行构建时。
    • 当需要确保同一产品族的对象一起工作时。

优点

  • 桥接模式:
    • 抽象与实现分离,提高了系统的灵活性和可维护性。
    • 可以独立地扩展抽象和实现,减少类的数量,避免类爆炸问题。
    • 实现细节透明,用户不需要了解实现细节。
  • 抽象工厂模式:
    • 确保同一产品族的对象一起工作,避免了不同产品族之间的不兼容问题。
    • 客户端不需要知道每个对象的具体类,简化了代码。
    • 符合开闭原则,添加新的产品族时,不需要修改现有代码。

缺点

  • 桥接模式:
    • 理解与设计难度较高,增加了系统的理解与设计难度。
    • 要求开发者在抽象层进行设计与编程,对开发者的抽象思维能力要求较高。
  • 抽象工厂模式:
    • 扩展产品族非常困难,增加一个新的产品族需要修改抽象工厂和所有具体工厂的代码。
    • 类的数量增加,增加了系统的复杂度。

示例

  • 桥接模式:假设有一个绘图程序,需要绘制不同形状(如圆形、矩形)和不同颜色(如红色、绿色)。通过桥接模式,可以将形状和颜色分离,形状作为抽象部分,颜色作为实现部分,从而独立地扩展形状和颜色
  • 抽象工厂模式:假设有一个跨平台的应用程序,需要创建不同操作系统的UI元素(如按钮、复选框)。通过抽象工厂模式,可以定义一个抽象工厂接口,为每个操作系统实现一个具体工厂类,从而创建符合该操作系统风格的UI元素

桥接模式可以避免类爆炸

桥接模式可以避免类爆炸的原因主要在于它通过将抽象与实现分离,使用组合而非继承来实现功能的扩展

传统继承方式导致类爆炸

假设一个系统存在两个独立变化的维度,例如形状(圆形、方形)和颜色(红色、蓝色)。如果使用传统的继承方式,每个维度的组合都需要一个单独的类。当增加新的形状或颜色时,类的数量会呈指数级增长。例如:
  • 原有形状:圆形、方形
  • 原有颜色:红色、蓝色
  • 组合类:RedCircleBlueCircleRedSquareBlueSquare
如果再增加一个形状(三角形),就需要新增两个类(RedTriangleBlueTriangle)。同样,如果增加一种颜色(绿色),就需要为每种形状新增一个类(GreenCircleGreenSquareGreenTriangle)。这种情况下,类的数量会迅速膨胀,导致代码难以维护和扩展

桥接模式避免类爆炸

桥接模式通过将抽象部分(如形状)与实现部分(如颜色)分离,使它们可以独立变化。具体来说:
  • 抽象部分:定义高层的抽象接口,例如形状的绘制方法。
  • 实现部分:定义具体的实现接口,例如颜色的填充方法。
  • 组合关系:抽象部分通过组合的方式持有实现部分的引用,而不是通过继承
以形状和颜色为例:
  • 定义一个抽象的Shape类,包含一个Color接口的引用。
  • 定义CircleSquare等具体形状类,继承自Shape
  • 定义RedColorBlueColor等具体颜色类,实现Color接口
在这种设计下,增加新的形状或颜色时,只需要新增对应的类,而不需要修改现有类。例如:
  • 增加三角形形状:新增Triangle类,继承自Shape
  • 增加绿色颜色:新增GreenColor类,实现Color接口。
这种分离和组合的方式,使得形状和颜色可以独立扩展,避免了类的指数级增长

总结

桥接模式通过将抽象与实现分离,并使用组合关系代替继承,有效避免了因多维度组合导致的类爆炸问题。这不仅减少了类的数量,还提高了系统的可维护性和扩展性
posted @ 2025-04-12 22:29  Taotao717  阅读(20)  评论(0)    收藏  举报