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

一、装饰器模式

1.1 概述

  • 定义:允许向一个现有的对象添加新的功能,同时又不改变其结构
  • 适用场景:需要动态地增加或撤销功能时,有大量独立的扩展,为支持每一种组合继承将产生大量的子类
  • 设计要点:注意装饰的顺序,用装饰的方式拓展功能容易出错,调试也更困难

1.2 类图

在这里插入图片描述

二、外观模式

2.1 概述

  • 定义:又名门面模式,为子系统中的一组接口提供一个一致的界面
  • 设计要点:无法阻止客户端调用子系统的接口,降低了系统功能的灵活性
  • 适用场景:
    • 客户端解耦:将子系统与客户端解耦
    • 重构解耦:重构系统时将系统分层,各层用外观角色对接
    • 擦屁股:保持原系统为一层,打包一个接口,继续开发后续

2.2 类图

在这里插入图片描述

  • 角色
  • 外观角色(Façade):这个类一般不负责具体的业务逻辑,只是一个委托类,具体的业务逻辑由子系统完成
  • 子系统(SubSystem):由多个类组成的具有某一特定功能的子系统

2.3 实现

  • 代码示例
    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()
    

三、组合模式

3.1 概述

  • 定义:将对象组合成树形结构以表示“部分-整体”的层次结构,
  • 设计要点:
    • 了解对象的组成结构
    • 各名词:组合模式是一种具有层次关系的树形结构,不能再分的叶子节点是最小的逻辑单元;具有子节点(由多个子组件组成)的组件称为也就是组合对象;
    • 限制:层次结构太深的场景中,组合结构会变得太庞杂
  • 适用场景:
    • 对象行为:组合对象与单个对象具有相同或类似行为(方法)
    • 对象关系:对象之间具有明显的“部分-整体”的关系时,或者具有层次关系

3.2 类图

在这里插入图片描述

  • 角色:
    • 组件的基类(Component):定义统一的方法feature、isComposite、isComposite用于判断一个组件是否为复合组件
    • 具体的组件:ComponentImplA、ComponentImplB
    • 复合组件(Composite):本身也是一个组件,因为它也实现了feature方法

3.3 实现

  • 代码示例
    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))
    

四、适配器模式

4.1 概述

  • 定义:将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作
  • 设计要点:过多地使用适配器,容易使代码结构混乱
  • 适用场景:
    • 适配老系统:现有系统需要使用老系统的类,而这些类的接口不符合现有系统的要求
    • 适配第三方:增加接入第三方的接口或SDK

4.2 类图

  • 继承方式实现
    在这里插入图片描述
  • 组合方式实现(推荐)
    在这里插入图片描述
  • 角色
    • 目标接口(Target):提供给用户调用的接口抽象
    • 待适配的类(Adaptee):要进行适配的对象类
    • 适配器(Adapter):是对Adaptee的适配,它将 Adaptee 的对象转换(包装)成符合 Target 接口的对象

4.3 实现

  • 类级实现

    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()
    
  • 对象级实现(推荐)

    # 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()
    

五、桥梁模式

5.1 概述

  • 定义:将抽象和实现解耦,使得两者可以独立地变化,与策略模式相似
  • 设计要点:注意与策略模式对比,桥梁模式为结构型模式,关注的是抽象和实现的分离,使得它们可以独立地发展;而策略模式为行为型模式关注的是对算法、规则的封装,使得算法可以独立于使用它的用户而变化
  • 适用场景:
    • 一个产品(或对象)有多种分类和多种组合,即两个(或多个)独立变化的维度,每个维度都希望独立进行扩展
    • 因为使用继承或因为多层继承导致系统类的个数急剧增加的系统,可以改用桥接模式来实现。

5.2 类图

在这里插入图片描述

  • 角色
    • 抽象化角色(Abstraction):主要职责是定义该角色行为,同时保存一个对实现化角色的引用
    • 修正抽象化角色:它引用实现化角色对抽象化角色进行修正
    • 实现化角色(Implementor):它是接口或者抽象类,定义角色必需的行为和属性
    • 具体实现化角色:它实现接口或抽象类定义的方法和属性
  • 应用场景:适合与两个维度以后都会扩展,如{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()
    

六、享元模式

6.1 概述

  • 定义:运用共享技术有效地支持大量细粒度对象的复用,对内存友好,对复杂度不友好
  • 设计要点:
    • 区分内外部状态:内部状态,享元对象内部并且不会随环境改变而改变的状态;外部状态,享元对象的外部状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入享元对象内部
    • 对象:必须是轻量级、细粒度的对象
  • 适用场景:一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费;缓存场景

6.2 类图

在这里插入图片描述

  • 角色
    • 享元对象(Flyweight):即你期望用来共享的对象,享元对象必须是轻量级对象,也就是细粒度对象
    • 享元工厂(FlyweightFactory):享元模式的核心角色,负责创建和管理享元对象,提供一个享元池

6.3 实现

  • 代码示例
    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("红色")
    
    ######################################################
    >>> 没有此颜色,创建颜色:红色
    >>> 没有此颜色,创建颜色:黑色
    >>> 调用已存在的颜色对象:红色
    

七、代理模式

7.1 概述

  • 定义:为一个对象提供一个替身,以控制对这个对象的访问,隐藏被代理对象的部分功能和服务,也可增加额外的功能
  • 设计要点:防止过于臃肿,拖慢访问速度,或过于复杂
  • 应用场景
    • 远程代理:不想或者不能直接引用一个对象时,如在移动端加载网页信息时预留占位符
    • 特殊用途代理:用于对象应该具有不同访问权限的场景,控制对原始对象的访问

7.2 类图

在这里插入图片描述

  • 角色:
    • 主题的抽象基类(Subject):负责定义操作、活动、任务的接口类
    • 代理类(ProxySubjec):代理RealSubject的功能,调用被代理类,并附加自己的操作
    • 真实主题类(RealSubject):Subject的具体实现类

7.3 实现

  • 代码示例
    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()
    

返回总目录

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 精通Python设计模式需要对Python编程语言有深入的理解,并且熟悉常用的设计模式设计模式是一种解决特定问题的经验总结,可以提供可复用的解决方案。 首先,精通Python设计模式需要掌握Python的基本语法和面向对象编程的概念。了解、对象、继承、多态等概念并能够熟练运用。 其次,熟悉常用的设计模式设计模式可以分为创建型、结构型和行为型。常见的设计模式包括单例模式、工厂模式、观察者模式、策略模式、装饰器模式等。对于每个模式,需要了解其定义、适用场景和解决的问题,同时能够根据具体的问题选择合适的模式。 此外,还需要能够在实际项目中运用设计模式。通过合理地运用设计模式,可以提高代码的可复用性和可扩展性,降低系统的维护成本。在使用设计模式时,需要根据具体的需求和情况进行权衡,避免过度设计和滥用设计模式。 最后,持续学习和实践是精通Python设计模式的关键。设计模式是一种经验,需要在实际开发中不断使用和改进。通过参与开源项目、阅读优秀代码和交流讨论等方式,不断提高自己的设计模式能力。 总之,精通Python设计模式需要熟悉Python语言并掌握常用的设计模式,能够在实际项目中灵活运用。通过不断学习和实践,可以进一步提高自己的设计模式水平。 ### 回答2: 精通Python设计模式是指对Python语言中各种设计模式及其应用有深入理解和熟练掌握的能力。 首先,精通Python设计模式需要对Python语言本身有较高的掌握程度,熟悉Python的语法、数据型、面向对象编程等基础知识。同时,需要了解Python常用的模块和库,如NumPy、Pandas、TensorFlow等,在项目中熟练运用。 其次,要精通Python设计模式,需要对常见的设计模式有深入的理解。设计模式是对软件设计经验的总结和抽象,可以解决某问题,并且能够提供可复用的设计方案。常见的设计模式有单例模式、工厂模式、观察者模式、装饰器模式等。对于每种设计模式,我们需要了解它的定义、适用场景、优缺点以及实际应用中的注意事项等。 最后,精通Python设计模式也需要具备实际项目经验。通过实践中运用设计模式解决具体问题,可以加深对设计模式的理解,并掌握如何将设计模式应用于实际项目中。同时,通过项目经验还可以锻炼解决问题的能力和代码质量。 总而言之,精通Python设计模式是掌握Python语言、了解常见设计模式、具备实际项目经验的综合能力。通过深入学习和实践,可以提高代码的可维护性、复用性和扩展性,从而更好地应对复杂的软件设计和开发任务。 ### 回答3: 精通Python设计模式是指对Python编程语言中各种设计模式的理解和运用达到了高级水平。 首先,理解设计模式的概念是基础。设计模式是在软件开发过程中用于解决常见问题和提供可复用解决方案的经验总结。在精通Python设计模式前,必须熟悉常见的设计模式,如创建型模式、结构型模式和行为型模式,并了解每个设计模式的特点和适用场景。 其次,精通Python设计模式需要掌握Python语言的特性和语法。熟练使用Python的面向对象编程(OOP)特性,如封装、继承和多态,能够更好地理解并实现设计模式。同时,熟悉Python中的函数式编程(FP)特性,如高阶函数、闭包和装饰器,能够更好地应用某些设计模式,如策略模式和装饰器模式。 其次,熟悉和掌握各种设计模式的具体实现和应用。例如,对于创建型模式中的工厂模式,可熟练使用Python的工厂函数或元实现;对于结构型模式中的适配器模式,可使用Python的继承或组合方式实现;对于行为型模式中的观察者模式,可利用Python的事件机制或回调函数实现。 最后,精通Python设计模式还需要对代码的质量和可维护性有一定的追求。设计模式并非银弹,不应盲目使用。在实际开发中,需要根据具体情况权衡设计模式的利弊,并结合项目的需求和团队的能力做出合理的选择和折中。 总的来说,精通Python设计模式需要综合考虑设计模式的基本概念、Python语言的特性和语法以及具体应用场景的需求,通过不断实践和学习,不断提高自己的设计思维和编码能力。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值