大话设计模式:第22章 桥接模式

第22章:桥接模式

继承带来的麻烦

对象的继承关系是在编译时就定义好了,所以无法在运行时改变从父类继承的实现。子类的实现与它的父类有非常紧密的依赖关系,以至于父类实现中的任何变化必然会导致子类发生变化。当需要复用子类时,如果继承下来的实现不适合解决新的问题,则父类必须重写或被其他更适合的类替换。这种依赖关系限制了灵活性并最终限制了复用性。

合成、聚合复用原则

合成、聚合复用原则(composition & aggregation reuse principle,CARP),尽量使用合成、聚合,尽量不要使用类继承。

合成(组合,composition)和聚合(aggregation)都是关联的特殊种类。

聚合:表示一种弱的“拥有”关系,体现的是A对象可以包含B对象,但B对象不是A对象的一部分;

合成:表示一种强的“拥有”关系,体现了严格的部分和整体的关系,部分和整体的生命周期相同。

例:大雁有两个翅膀,翅膀与大雁是部分和整体的关系,并且它们的生命周期是相同的,于是大雁和翅膀就是合成关系;大雁是群居动物,所以每只大雁都是属于一个雁群,一个雁群可以有多只大雁,所以大雁和雁群是聚合关系。

合成、聚合复用原则的优点是优先使用对象的合成、聚合将有助于你保持每个类被封装并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。

紧耦合v.s.松耦合

  • 紧耦合(继承)

在这里插入图片描述

  • 松耦合(聚合)

在这里插入图片描述

松耦合代码

手机软件抽象类

在这里插入图片描述

游戏、通讯录等具体类

在这里插入图片描述

手机品牌类

在这里插入图片描述

品牌N品牌M具体类

在这里插入图片描述
客户端调用代码

在这里插入图片描述

增加MP3音乐播放类

在这里插入图片描述

增加品牌S

在这里插入图片描述

合成、聚合复用原则:优先使用对象的合成或聚合,而不是类继承。继承是一种强耦合的结构,父类变,子类必须变,与合成、聚合相比,继承容易造成不必要的麻烦。所以使用继承时,一定要在is-a的关系时再考虑使用。

桥接模式

桥接(bridge)模式:将抽象部分与它的实现部分分离,使它们都可以独立地变化。

抽象与它的实现分离不是让抽象类与其派生类分离,因为这没有任何意义。实现指的是抽象类和它的派生类用来实现自己的对象。由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。

在这里插入图片描述

Implementor

在这里插入图片描述

ConcreteImplementorAConcreteImplementorB等派生类

在这里插入图片描述

Abstraction

在这里插入图片描述

RefinedAbstraction

在这里插入图片描述

客户端实现

在这里插入图片描述

桥接模式所说的“将抽象部分与它的实现部分分离”是实现系统可能有多角度分类,每一种分类都有可能变化,那么就把这种多角度分离出来让它们独立变化,减少它们之间的耦合。

在需要多角度去分类实现对象时,只用继承会造成大量的类增加,不满足开放-封闭原则,此时应该要考虑桥接模式。

桥接模式示例

任务:手机应用(多品牌,多应用)

在这里插入图片描述

from abc import ABCMeta, abstractmethod
from typing import Text

class HandsetSoft(metaclass=ABCMeta):
    """
    手机软件抽象类(Implementor)
    """
    @abstractmethod
    def run(self) -> None:
        pass
    
class HandsetGame(HandsetSoft):
    """
    手机游戏类
    """
    def run(self) -> None:
        print("运行手机游戏")
        
class HandsetAddressList(HandsetSoft):
    """
    手机通讯录类
    """
    def run(self) -> None:
        print("运行手机通讯录")
class Handset(metaclass=ABCMeta):
    """
    手机品牌类(Abstraction)
    """
    def __init__(self) -> None:
        self._soft = None
        
    def set_handset_soft(self, soft: HandsetSoft) -> None:
        self._soft = soft
        
    @abstractmethod
    def run(self) -> None:
        pass
class HandsetBrandN(Handset):
    """
    手机品牌N
    """
    def run(self) -> None:
        print("手机N")
        self._soft.run()
        
class HandsetBrandM(Handset):
    """
    手机品牌M
    """
    def run(self) -> None:
        print("手机M")
        self._soft.run()
# 客户端调用代码

if __name__ == "__main__":
    
    ab = HandsetBrandN()
    
    ab.set_handset_soft(HandsetGame())
    ab.run()
    
    ab.set_handset_soft(HandsetAddressList())
    ab.run()
    
    ab = HandsetBrandM()
    
    ab.set_handset_soft(HandsetGame())
    ab.run()
    
    ab.set_handset_soft(HandsetAddressList())
    ab.run()
手机N
运行手机游戏
手机N
运行手机通讯录
手机M
运行手机游戏
手机M
运行手机通讯录
class HandsetBrandS(Handset):
    """
    手机品牌S
    """
    def run(self) -> None:
        print("手机S")
        self._soft.run()
        
class HandsetMP3(HandsetSoft):
    """
    手机MP3类
    """
    def run(self) -> None:
        print("运行手机MP3音乐播放器")
# 客户端调用代码

if __name__ == "__main__":
    
    ab = HandsetBrandS()
    
    ab.set_handset_soft(HandsetMP3())
    ab.run()
    

手机S
运行手机MP3音乐播放器

猜你喜欢

转载自blog.csdn.net/zhaoyin214/article/details/106006186
今日推荐