桥接模式
定义
桥接模式(Bridge Pattern):将抽象部分与它的实现部分解耦,使它们都可以独立地变化。
这种类型的设计模式属于结构型模式,它通过提供抽象化和实现化之间的桥接结构,来实现二者的解耦。
场景
系统可能有多个维度分类,每一种维度都可能变化。在有多种可能会变化的情况下,用继承会造成类爆炸问题,扩展起来不灵活。
1.如果一个系统需要在构件的抽象化角色和具体化角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系,通过桥接模式可以使它们在抽象层建立一个关联关系。
2.对于那些不希望使用继承或因为多层次继承导致系统类的个数急剧增加的系统,桥接模式尤为适用。
3.一个类存在两个独立变化的维度,且这两个维度都需要进行扩展。
看不懂?没关系,我们来看生活中最通俗易懂的例子。
例如,有大中小规格的笔,有红蓝黄三种颜料。如果需要不同颜色,不同规格的笔有如下两种设计方法:
1.为每一种规格的毛笔都提供三种颜料的版本。
2.将笔和颜料分开,使用的时候自由组合。
上面第一种设计方法,其类(版本)的数量计算公式为3*3=9,随着笔的规格和颜料种类的不断增长,当笔有9种规格,颜色有9种,那么就会出现9*9=81种类,如果再来一个维度--材质,假设有4种材质--金、银、铜、铁,那么就会出现9*9*4=324种类,其类数量的增加速度为O(n!),需要维护庞大的种类集合,显然不可行。
而第二种设计方法,其类的数量计算公式为3+3=6,就算有9种规则,9种颜色,4种材质,也就是9+9+4=22而已。
下面来看第二种设计方法的实现。
实现
这是第二种设计方法的实现。
# 抽象规格类
class Size(object):
def __init__(self, size):
self.color = None
self._size = size
# match_color 作为桥接, 各自的变化, 不影响其他分类
def match_color(self, color):
self.color = color
def produce(self):
print(f"生产 规格为: {self._size} 颜色为: {self.color.color()} 的笔")
# 大号规格,具体规格类,继承抽象规格类
class BigSize(Size):
def __init__(self):
super(BigSize, self).__init__('大号')
# 中号
class MiddleSize(Size):
def __init__(self):
super(MiddleSize, self).__init__('中号')
# 小号
class SmallSize(Size):
def __init__(self):
super(SmallSize, self).__init__('小号')
# 抽象颜色类
class Color(object):
def __init__(self, color):
self._color = color
def color(self):
return self._color
# 红色
class RedColor(Color):
def __init__(self):
super(RedColor, self).__init__('红色')
# 蓝色
class BlueColor(Color):
def __init__(self):
super(BlueColor, self).__init__('蓝色')
# 黄色
class YellowColor(Color):
def __init__(self):
super(YellowColor, self).__init__('黄色')
if __name__ == "__main__":
red = RedColor()
blue = BlueColor()
yellow = YellowColor()
big_size = BigSize()
big_size.match_color(red)
big_size.produce()
big_size.match_color(blue)
big_size.produce()
big_size.match_color(yellow)
big_size.produce()
middle_size = MiddleSize()
middle_size.match_color(red)
middle_size.produce()
middle_size.match_color(blue)
middle_size.produce()
middle_size.match_color(yellow)
middle_size.produce()
small_size = SmallSize()
small_size.match_color(blue)
small_size.produce()
small_size.match_color(red)
small_size.produce()
small_size.match_color(yellow)
small_size.produce()
优点
1.抽象和实现的分离。
2.优秀的扩展能力。
3.实现细节对客户透明。
缺点
桥接模式的引入会增加系统的理解与设计难度,由于聚合关联关系建立在抽象层,要求开发者针对抽象进行设计与编程。