Python实现软件设计模式8:桥接模式 Bridge Pattern

发布时间 2024-01-11 12:58:06作者: 爱吃砂糖橘的白龙

动机

将抽象部分与实现部分分离,使他们都可以独立地变化。用抽象关联取代传统的多层继承。将类之间的静态继承关系转换为动态的对象组合关系。

上图展示的软件系统中存在两个独立地变化维度,分别是抽象类(Abstraction)和实现类(Implementor),它俩都是接口、都分别可以独立地扩展出多个子类。抽象类中关联(委派)一个实现类对象。作为区分,通常让将宏大的、公共的类作为抽象类,将细粒度的、容易重用的类作为实现类。

主要角色

  • Abstraction 抽象类接口
  • RefinedAbstractionA\B\C 扩展抽象类
  • Implementor 实现类接口
  • ConcreteImplementorA\B\C 具体实现类
  • Client 客户端

案例

以蜡笔和毛笔绘画进行举例,蜡笔把颜色和尺寸型号两个变化维度耦合在一起,毛笔将颜色和型号实现了分离,增加新的颜色或尺寸型号对另一方面没有任何影响。

对于每一只毛笔,大小是固定的,但是颜色是可以变化选择的,因此将毛笔的尺寸型号定义在抽象部分中,将颜色属性声明、定义在实现部分中。

Python代码

from abc import ABC,abstractmethod
import typing

class Color(ABC):   # 抽象类
    @abstractmethod # 笔类型、图形类型
    def bepaint(self, penType : str, name : str):
        pass

class Black(Color):
    def bepaint(self, penType: str, name: str):
        print(f"{penType} 黑色的 {name}.")

class Blue(Color):
    def bepaint(self, penType: str, name: str):
        print(f"{penType} 蓝色的 {name}.")

class Green(Color):
    def bepaint(self, penType: str, name: str):
        print(f"{penType} 绿色的 {name}.")

class Red(Color):
    def bepaint(self, penType: str, name: str):
        print(f"{penType} 红色的 {name}.")

class Yellow(Color):
    def bepaint(self, penType: str, name: str):
        print(f"{penType} 黄色的 {name}.")


class Pen(ABC):
    def __init__(self):
        self._color = None
    
    def setColor(self, color):
        self._color = color
    
    @abstractmethod
    def draw(self, name):
        pass

class BigPen(Pen):
    def draw(self, name):
        penType = "大号毛笔绘制"
        self._color.bepaint(penType, name)

class MiddlePen(Pen):
    def draw(self, name):
        penType = "中号毛笔绘制"
        self._color.bepaint(penType, name)

class SmallPen(Pen):
    def draw(self, name):
        penType = "小号毛笔绘制"
        self._color.bepaint(penType, name)
    
class Client:
    def __init__(self, col: str, pen:  str):  # 用户注入毛笔的 颜色 和 尺寸型号
        self.Color  = eval(col)()
        self.PenType = eval(pen)()
        try:
            self.Color  = eval(col)()
        except NameError:
            print("Error! 所指定颜色不存在!")
        
        try:
            self.PenType = eval(pen)()
        except NameError:
            print("Error! 所指定毛笔类型不存在!")

    def run(self, shape:str):  # 指定绘制的图案或形状
        self.PenType.setColor(self.Color)
        self.PenType.draw(shape)

if __name__ == '__main__':
    c1 = Client(col = 'Red', pen = 'SmallPen')
    c1.run('乌龟')

    c2 = Client(col = 'Blue', pen = 'MiddlePen')
    c2.run('飞机')

总结

优点

  • 分离抽象接口及实现部分
  • 可以取代多层继承方案,极大地减少子类的个数
  • 提高系统的可扩展性,在两个变化维度中任意扩展一个维度,不需要修改原有系统,符合开闭原则

缺点

  • 关联关系建立在抽象,会增加系统的理解与设计难度
  • 正确识别两个独立的变化维度有难度