• python设计模式(三)--结构类设计模式


    一、装饰器模式

    二、外观模式

    2.1 概述

    • 定义:又名门面模式,对客户端提供一个封装(包含多个子系统)的接口,封装思想
    • 特点
      • 优点:实现子系统与客户端松耦合,客户端屏蔽子系统组件,减少了客户端所需处理的对象数目
      • 缺点:无法阻止客户端调用子系统的接口

    2.2 实现

    • 代码示例
      class CPU:
          def run(self):
              print("CPU开始工作")
      
      
      class Memory:
          def run(self):
              print("内存开始工作")
      
      
      class Computer:
          def __init__(self):
              self.cpu = CPU()
              self.memory = Memory()
      
          def start(self):
              self.cpu.run()
              self.memory.run()
      
      
      if __name__ == "__main__":
          computer = Computer()
          computer.start()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23

    三、组合模式

    3.1 概述

    • 定义:将对象组合成树形结构以表示“部分-整体”的层次结构
    • 优点:客户端可以一致地使用组合对象和单个对象,更容易增加新类型的组件

    3.2 实现

    • 代码示例
      from abc import ABCMeta, abstractmethod
      
      
      # 抽象组件基类
      class Graphic(metaclass=ABCMeta):
          @abstractmethod
          def draw(self):
              pass
      
      
      # 叶子节点:不可再分,最底层
      class Point(Graphic):
          def __init__(self, x, y):
              self.x = x
              self.y = y
      
          def __str__(self):
              return f"点({self.x},{self.y})"
      
          def draw(self):
              print(str(self))
      
      
      # 复合节点:两个点p1、p2是线的子节点
      class Line(Graphic):
          def __init__(self, p1, p2):
              self.p1 = p1
              self.p2 = p2
      
          def __str__(self):
              return f"线段({self.p1},{self.p2})"
      
          def draw(self):
              print(str(self))
      
      
      # 顶层复合节点:所有传入的iterable对象都是Picture对象子节点
      class Picture(Graphic):
          def __init__(self, iterable):
              # 初始化对象时遍历iterable向Picture添加对象
              self.children = []
              for elem in iterable:
                  self.add(elem)
      
          def add(self, graphic):
              self.children.append(graphic)
      
          def draw(self):
              # 遍历运行每个对象的draw方法
              for elem in self.children:
                  elem.draw()
      
      
      # 客户端
      if __name__ == "__main__":
          # 组合pic1的树形对象组合
          p1 = Point(0, 0)
          l1 = Line(Point(1, 1), Point(2, 2))
          l2 = Line(Point(3, 3), Point(4, 4))
          pic1 = Picture([p1, l1, l2])
      
          # 组合pic2的树形对象组合
          p2 = Point(5, 5)
          l3 = Line(Point(6, 6), Point(7, 7))
          pic2 = Picture([p2, l3])
      
          # 组合pic树形对象组合
          pic = Picture([pic1, pic2])
          # 递归的调用各个子对象的draw方法
          pic.draw()
      ##########################################
      >>> 点(0,0)
      >>> 线段(点(1,1),点(2,2))
      >>> 线段(点(3,3),点(4,4))
      >>> 点(5,5)
      >>> 线段(点(6,6),点(7,7))
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76

    四、适配器模式

    4.1 概述

    • 定义:作为两个不兼容的接口之间的桥梁
    • 角色
      • 目标接口(Target)
      • 待适配的类(Adaptee)
      • 适配器(Adapter)

    4.2 实现

    • 类级实现

      class OldCoding:
          def show_msg(self):
              print("调用了老代码的接口")
      
      
      class NewCoding:
          def print_msg(self):
              print("调用了新代码的接口")
      
      
      # 适配器与新类的方法同名
      class CodingAdapter(OldCoding, NewCoding):
      
          # 因多继承,可以直接调用方法
          def print_msg(self):
              self.show_msg()
      
      
      if __name__ == "__main__":
          # 新类的新方法
          p1 = NewCoding()
          p1.print_msg()
          # 适配器的同名方法
          p2 = CodingAdapter()
          p2.print_msg()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
    • 对象级实现

      # OldCoding、NewCoding跟类级实现相同
      class OldCoding:
          def show_msg(self):
              print("调用了老代码的接口")
      
      
      class NewCoding:
          def print_msg(self):
              print("调用了新代码的接口")
      
      
      # 适配器同新类方法同名
      class CodingAdapter(OldCoding):
      	# code为OldCoding对象,即待适配对象
          def __init__(self, code):
              self.code = code
      
          # 同名的方法内部调用了老类的方法
          # 传入的是老类的类对象
          def print_msg(self):
              self.code.show_msg()
      
      
      if __name__ == "__main__":
          # 新类的新方法
          c1 = NewCoding()
          c1.print_msg()
          # 适配器用新类的方法,内部调用老类的方法
          # 适配器接受的是老类的对象
          c2 = CodingAdapter(OldCoding())
          c2.print_msg()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31

    五、桥梁模式

    5.1 概述

    • 定义:将抽象和实现解耦,使得两者可以独立地变化
    • 角色
      • 抽象化角色:它的主要职责是定义出该角色的行为,同时保存一个对实现化角色的引用,该角色一般是抽象类。
      • 实现化角色:它是接口或者抽象类,定义角色必需的行为和属性。
      • 修正抽象化角色:它引用实现化角色对抽象化角色进行修正。
      • 具体实现化角色:它实现接口或抽象类定义的方法和属性。
    • 应用场景:适合与两个维度以后都会扩展,如{a,b,c}与{1,2,3}组合,继承需要写9个类,桥只需要6个,扩展的话得指数级增长

    5.2 实现

    • 代码示例
      from abc import ABCMeta, abstractmethod
      
      
      class Shape(metaclass=ABCMeta):
      
          # 初始化形状类对象同时保存颜色对象
          def __init__(self, color):
              self.color = color
      
          # 此处会调用颜色对象方法
          @abstractmethod
          def draw(self):
              pass
      
      
      class Color(metaclass=ABCMeta):
          @abstractmethod
          def paint(self, shape):
              pass
      
      
      # 可以扩展形状,符合对扩展开放,对修改封闭原则
      # 还可以实现三角形、方形等类,只要以圆类为模版即可
      class Circle(Shape):
          name = "圆形"
      
          # 具体类里交叉调用:形状类里调用颜色方法
          def draw(self):
              self.color.paint(self)
      
      
      # 可以扩展颜色,符合对扩展开放,对修改封闭原则
      # 还可以实现红、蓝等类,只要以黑类为模版即可
      class Black(Color):
          # 具体类里交叉调用:颜色类里调用形状属性
          def paint(self, shape):
              print("黑色的", shape.name)
      
      
      if __name__ == "__main__":
          # paint方法是包在Black实例对象里传给Circle类初始化形状对象的
          s = Circle(Black())
          # 此处耦合,在具体类实现的层级耦合
          # s为Circle实例
          # 其方法draw调用抽象基类的init方法存的Color实例的paint方法
          # paint方法又用到Circle类的name属性
          s.draw()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47

    六、享元模式

    6.1 概述

    • 定义:享元模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象,对内存友好,对复杂度不友好
    • 角色
      • 抽象享元类
      • 具体享元类:实现了Flyweight,指定内部状态。
      • 享元创建工厂类

    6.2 实现

    • 代码示例
      class ColorFlyWeight:
          """颜色享元类"""
          def __init__(self, name):
              self.name = name
      
      
      class ColorFactory:
          """颜色创建工厂"""
          def __init__(self):
          	# 此处存储待共享的对象
              self.color = {}
      
      	# 享元模式针对只读对象,在多次读取的过程不重复创建对象
          def get_color(self, color_name):
          	# 字典的方法get
              color = self.color.get(color_name)
              # 如果存在于init的color中,直接返回
              if color:
                  print("调用已存在的颜色对象:" + color_name)
                  return color
              # 否则创建对象,并将对象以键值对方式加入init方法中的color字典中
              print("没有此颜色,创建颜色:" + color_name)
              color = ColorFlyWeight(color_name)
              self.color[color_name] = color
              return color
      
      
      if __name__ == "__main__":
          factory = ColorFactory()
          Red_color = factory.get_color("红色")
          Black_color = factory.get_color("黑色")
          Red2_color = factory.get_color("红色")
      
      ######################################################
      >>> 没有此颜色,创建颜色:红色
      >>> 没有此颜色,创建颜色:黑色
      >>> 调用已存在的颜色对象:红色
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37

    七、代理模式

    7.1 概述

    • 定义:为一个对象提供一个替身,以控制对这个对象的访问
    • 角色:
      • 接口类:通过接口或抽象类声明真实角色实现的业务方法
      • 代理类:实现接口,调用被代理类,并附加自己的操作
      • 被代理类:实现接口,业务的真实处理类
    • 应用场景
      • 远程代理:为一个对象的地址空间提供局部代表。
      • 虚拟代理:根据需要来创建开销较大的对象。
      • 保护代理:用于对象应该具有不同访问权限的场景,控制对原始对象的访问。
      • 智能指引:取代简单的指针,它在访问对象时执行一些附加操作。

    7.2 实现

    • 代码示例
      from abc import abstractmethod, ABCMeta
      
      
      # 定义接口
      class Connection(metaclass=ABCMeta):
      
          @abstractmethod 
          def request(self):
              pass
      
      
      # 被代理类实现此接口
      class RealConnection(Connection):
      
          def request(self):
              print("真实服务端收到请求")
      
      
      # 代理类实现此接口,并进行拓展
      class ProxyConnection(Connection):
      
          def request(self):
              print("代理服务端进行额外操作")
              # 此处构造被代理对象的实例,并继续逻辑操作
              RealConnection().request()
      
      
      if __name__ == '__main__':
          # 客户端调用代理对象,并调用代理对象的接口
          p = ProxyConnection()
          p.request()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31

    返回总目录

  • 相关阅读:
    IINA for Mac v1.3.5 音视频软件 安装教程(保姆级)
    多维时序 | MATLAB实现WOA-CNN-BiGRU-Attention多变量时间序列预测(SE注意力机制)
    vue开发,如何结合chatgpt
    博客构建性能优化笔记 | 提速 3 倍
    CAD长方形纤维插件2D
    Ubuntu 20.04上安装Datalog Disassembly工具的过程
    PCL_点云分割_基于法线微分分割
    ATF源码篇(一):起始
    React富文本编辑器开发(十一)命令与编辑器
    logback(二)springboot配置日志文件格式、logback-spring配置文件详解
  • 原文地址:https://blog.csdn.net/chucksun0426/article/details/125905284