跳到主要内容

桥接模式

桥接模式将类的抽象部分与其实现部分分离,使它们可以独立变化。这种模式有助于解决多维度变化的问题。

示例

这听起来比较让人难以理解,但实际上桥接模式的概念非常简单,很可能你在开发过程中已经不知不觉地使用过它。

例如,我们之前一直使用门的例子来解释设计模式。我们通常会有 Door, IronDoor, WoodenDoor 这几个类,但如果再引入 Color 的概念,那么就会有 RedIronDoor, BlueIronDoor, RedWoodenDoor, BlueWoodenDoor 等多个类——很明显,类的数量将随属性的增加而呈指数级增长。

为了避免这种情况,我们会将继承关系改为组合关系,即将 Color 作为一个属性,而不是一个类;对于 Material 也是一样。这样,我们就可以通过组合不同的对象来实现不同颜色和材质的门,而不需要为每种属性都创建一个新的类。

结构

桥接模式示意图桥接模式示意图

客户端直接与抽象类交互,抽象类则与实现类交互。抽象类则封装了实现类的接口和属性,使得客户端可以通过抽象类来访问实现类。

备注

某种程度上,这也像是遥控器和电视机的关系。遥控器是抽象类,电视机是实现类,遥控器通过按钮来控制电视机。

应用场景

  • 当希望在几个独立维度上变化一个类时
  • 当需要在运行时切换不同实现时

优缺点

优点

  • 客户端代码仅与高层抽象部分进行互动,对具体实现不了解
  • 单一职责原则:抽象部分专注于处理高层逻辑,实现部分处理平台细节。
  • 开闭原则:可以新增抽象部分和实现部分,且它们之间不会相互影响。

缺点

  • 抽象部分和实现部分分离,增加了代码复杂度,尤其是高内聚的系统

代码示例

下面是一个使用桥接模式的 Python 示例,其中 Door 是抽象类,DoorSpec 是实现类。FrontDoor 是对 Door 的具体实现,WoodenDoorSpec 是对 DoorSpec 的具体实现。

# [x] Pattern: Bridge
# Allows to separate an abstraction from its implementation so that the two can vary independently

# Why we use it
# When one class has some attributes that are not related to the main class
# While these attributes can be implemented in a separate class

from abc import ABC
from dataclasses import dataclass


class DoorSpec(ABC):
width: int
height: int
material: str

def area(self):
return self.width * self.height

@dataclass
class WoodenDoorSpec(DoorSpec):
def __init__(self, width: int, height: int):
self.width = width
self.height = height
self.material = 'wood'

@dataclass
class Door(ABC):
spec: DoorSpec

def tell(self):
print(f"Door with area {self.spec.area()} and material {self.spec.material}")

@dataclass
class FrontDoor(Door):
def __init__(self, spec: DoorSpec):
self.spec = spec


def main():
wood_door_spec = WoodenDoorSpec(10, 20)
front_door = FrontDoor(wood_door_spec)
front_door.tell()


if __name__ == '__main__':
main()