桥接模式(Bridge Design Pattern)有两种理解方式,它们分别是:
- 将抽象和实现解耦,是它们能够独立变化。
- 一个类或者功能存在多个独立变化的维度,通过组合的方式,让多个维度可以独立进行扩展。
桥接模式的核心是:用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度,防止继承关系太复杂导致类臃肿而难以维护。
桥接模式优缺点
优点
- 抽象和实现分离,方便扩展
- 符合组合优于继承原则
- 符合开闭原则,新增改动小
- 系统灵活性强
缺点
- 由于抽象和实现的解耦,整体结构也变得抽象和复杂,能正确地识别出系统中两个独立变化的维度,这增加了系统的理解与设计难度。
- 桥接模式要求正确识别出系统中多个独立变化的维度,因此其使用范围有一定的局限性。
应用场景
- 当一个对象有多个变化因素的时候,并且多个因素之间的变化独立。如手机这个对象,有品牌、颜色、配置等多个变化维度,维度之间独立变化。
- python中自带的logging模块,通过分别设置formatter、level、handler,实现生成特定结构的日志记录对象。
- 常用的监控组件实现监控级别、通知等级、通知方式分别设置,实现自定义的监控模式。
使用方式
下面我们通过一个手机的案例,用 python 实现一个桥接模式。
在手机中,我们有品牌、颜色、配置等多个维度,每个维度之间是独立变化的。
假设我们有两个品牌,两种颜色,两种配置,如果通过继承的方式表达所有的手机,需要2x2x2=8种类才能表示所有的手机。
而通过桥接模式,使用组合的方式,我们只需要品牌、颜色、配置3种类总计6个类就能表示所有的手机,并且可以很方便的替换各个维度。(当类别越多时,桥接模式的好处就越明显。)
类的构成
颜色类
品牌类
配置类
手机类(用于展示手机的各项参数)
颜色类
有 blue、red 两种颜色类,通过 get_color 方法获取颜色。
class Color(ABC):
@abstractmethod
def get_color(self):
"""打印颜色"""
raise NotImplementedError("要实现")
class Blue(Color):
def get_color(self):
print("blue")
class Red(Color):
def get_color(self):
print("red")
品牌类
有华为、苹果两种品牌类,通过 get_brand 方法获取手机的品牌。
class Brand(ABC):
@abstractmethod
def get_brand(self):
"""打印品牌"""
raise NotImplementedError("要实现")
class HuaWei(Brand):
def get_brand(self):
print("华为手机")
class Apple(Brand):
def get_brand(self):
print("苹果手机")
配置类
有 pro、max 两种配置类,通过 get_config 方法获取配置详情。
class Configuration(ABC):
@abstractmethod
def get_config(self):
"""打印配置"""
raise NotImplementedError("要实现")
class Pro(Configuration):
def get_config(self):
print("4核8g")
class Max(Configuration):
def get_config(self):
print("8核16g")
手机类
手机类是实现桥接模式最重要的实现类,在手机类中,我们分别注入 颜色、品牌、配置信息,然后把一台手机完整的参数信息打印出来。
class Phone:
def __init__(self, color: Color, brand: Brand, config: Configuration):
self.color = color
self.brand = brand
self.config = config
def show_phone(self):
"""展示手机"""
self.color.get_color()
self.brand.get_brand()
self.config.get_config()
# 手机1
phone1 = Phone(Blue(), HuaWei(), Max())
phone1.show_phone()
# 手机2
phone2 = Phone(Red(), Apple(), Max())
phone2.show_phone()
总结
桥接模式通过运用组合优于继承的原则,将一个功能类识别并拆分成多个相互独立的维度进行独立扩展,很好地实现了高扩展性和灵活性的特点。但是同时,也使整体结构也变得抽象和复杂,增加了系统的理解与设计难度。
对于能够比较明显拆分成独立维度的类,桥接模式是一种非常好用并且常见的设计模式与思想。