Python面经【9】- Python设计模式专题-下卷

2023-12-12 10:30

本文主要是介绍Python面经【9】- Python设计模式专题-下卷,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Python面经【9】- Python设计模式专题-下卷

  • 三、 工厂模式
    • 1. 简单工厂:【静态方法】
    • 2. 工厂方法
    • 3. 抽象工厂
    • 四、 建造者模式
      • 1. 不使用设计模式
      • 2. 使用设计模式

三、 工厂模式

工厂模式是最常用的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象
概念:创建一个对象的接口,让其子类自己决定实例化哪一个工厂类。工厂模式让类的实例化推迟到子类中进行。
主要解决:主要解决接口选择的问题
何时使用:我们明确计划不同条件下创建不同实例时。

在工厂设计模式中,客户端可以请求一个对象,而无需知道这个对象来自哪里;也就是,使用哪个类来生成这个对象。工厂背后的思想是简化对象的创建。与客户端自己基于实例化直接创建对象相比,基于一个中心化函数来实现,更易于追踪创建了那些对象。
通过将创建对象的代码和使用对象的代码解耦,工厂能够降低应用维护的复杂度。
工厂方法创建对象时,我们并没有与某个特定类耦合/绑定一起,而只是通过调用某个函数来提供关于我们想要什么的部分信息。这意味着修改这个函数比较容易,不需要同时修改使用这个函数的代码。

工厂通常有三种形式:
(1) 简单工厂:简单工厂并不是一个真正的设计模式,更像是一种编程习惯,它通过一个单独的类来创建实例,这个类通常包含一个静态方法,根据对不同的输入参数返回不同的对象;
(2) 工厂方法:工厂方式模式通过定义一个用于创建对象的接口,让子类决定实例化哪个类。这种模式使一个类的实例化延迟到其子类。
(3) 抽象工厂:它是一组用于创建一系列相关事物对象的工厂方法。

1. 简单工厂:【静态方法】

统一使用一个类作为对外接口,根据参数的不同,去选择实例化不同的类。

1. """2. 两个产品(两种类型的书)3. """4. class TechnicalBooks(object):5.     """技术书籍"""7.     def publish(self):8.         return "Python-Book"9.  
10. class LiteraryBooks(object):
11.     """文学书籍"""
12.  
13.     def publish(self):
14.         return "Black Hole Book"
15.  
16. # 现在我们有两种类型的书,分别是TechnicalBooks和LiteraryBooks的书
17. # 按照我们平常的方法来实例化的话,此时创建对象时是会对客户端暴露真正创建的类
18. it_books = TechnicalBooks()
19. ly_books = LiteraryBooks()
20.  
21. # 这时我们就可以构造一个"简单工厂"把所有实例化的过程封装在里面,把真正实例的类隐藏起来
22. class SimpleFactory(object):
23.     """简单工厂"""
24.     @staticmethod
25.     def publish_book(name):
26.         if name == 'technical':
27.             return TechnicalBooks()
28.         elif name == 'literary':
29.             return LiteraryBooks()
30.  # 通过类调用:class_name.fun_name()
31. it_books2 = SimpleFactory.publish_book('technical')
32. ly_books2 = SimpleFactory.publish_book('literary')

简单工厂的好处在于,把不同的类实例化统一到一个“工厂”,即不对外暴露真正的创建类,也提供了一个对外的统一接口。但是简单模式有一个缺点,那就是违背了soild的“开闭原则”,加入我们还需要增加一种书籍,那就必须要对简单工厂SimpleFactory进行源码的修改。
简单工厂的使用场景:

  • 已经确定有多少具体的类,不会再增加的情况下使用。

2. 工厂方法

上面的简单工厂我们知道了,如果新增一些类型的时候会违背软件设计中的开闭原则,但是我们希望再扩展新类时,不要修改原来的代码,这个时候我们可以在简单工厂的基础上把SimpleFactory抽象成不同的工厂,每个工厂对应生成自己的产品,这就是工厂方法。

1. """2. 两个产品(两种类型的书)3. """4. from abc import ABC, abstractmethod5. # 真正进行实例化的类6. class TechnicalBooks(object):7.     """技术书籍"""8.     def publish(self):9.         return "Python-Book"
10.  
11. class LiteraryBooks(object):
12.     """文学书籍"""
13.     def publish(self):
14.         return "Black Hole Book"
15.  
16. # 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
17. class AbstractFactory(metaclass=abc.ABCMeta):
18.     """抽象工厂"""
19.     @abstractmethod
20.     def publish_book(self):
21.         pass
22.  
23. class TechnicalFactory(AbstractFactory):
24.     """技术书籍工厂"""
25. 
26.     def publish_book(self):
27.         return TechnicalBooks()
28.  
29. class LiteraryFactory(AbstractFactory):
30.     """文学书籍工厂"""
31.  
32.     def publish_book(self):
33.         return LiteraryBooks()
34.  
35. it_books2 = TechnicalFactory().publish_book()   
36. ly_books2 = LiteraryFactory().publish_book()    # 如果通过类调用是不带括号的# 该代码带括号等价于先创建实例然后通过实例调用方法

这样每个工厂就只负责生产自己的产品,避免了在新增产品时需要修改工厂的代码,遵循了“开闭原则”,如果需要新增产品时,只需要增加相应的工厂即可。
比如要增加一种小说类型的书籍,只需增加一个NovelBooks类和NovelFactory类。
工厂方法的使用场景:

  • 当系统中拥有的子类很多,并且以后可能还需要不断拓展增加不同的子类时。
  • 当设计系统时,还不明确具体有那些类时。

在工厂方法中,使用者不需要知道具体的产品类名,只需要知道其对应的工厂即可。

3. 抽象工厂

工厂方法解决了“开闭原则”的问题,但是我们出版书籍之前肯定还有其他的步骤,比如印刷。如果要每一个步骤我们就要写一个对应的工厂类,那我们就会需要创建很多多多的类了。为了解决这个问题,我们就需要抽象工厂类,让一个工厂可以生产同一类的多个产品或多个动作(步骤),这就是抽象工厂。

1. """2. 两个产品(两种类型的书)3. """4. import abc5.  6. # 印刷书籍7. class PrintingTechnicalBooks(object):8.     """印刷技术书籍"""9.     def printing(self):
10.         return "Print-Python-Book"
11.  
12. class PrintingLiteraryBooks(object):
13.     """印刷文学书籍"""
14.     def printing(self):
15.         return "Print Black Hole Book"
16.  
17. # 出版书籍
18. class TechnicalBooks(object):
19.     """出版技术书籍"""
20.     def publish(self):
21.         return "Python-Book"
22.  
23. class LiteraryBooks(object):
24.     """出版文学书籍"""
25.     def publish(self):
26.         return "Black Hole Book"
27.  
28. # 抽象工厂:先定义抽象类,然后每种类型的书籍都有自己对于的工厂
29. class AbstractFactory(metaclass=abc.ABCMeta):
30.     """抽象工厂"""
31.  
32.     @abc.abstractmethod
33.     def print_book(self):
34.         pass
35.  
36.     @abc.abstractmethod
37.     def publish_book(self):
38.         pass
39.  
40. class TechnicalFactory(AbstractFactory):
41.     """技术书籍工厂"""
42.  
43.     def print_book(self):
44.         return PrintingTechnicalBooks()
45.  
46.     def publish_book(self):
47.         return TechnicalBooks()
48.  
49. class LiteraryFactory(AbstractFactory):
50.     """文学书籍工厂"""
51.     def print_book(self):
52.         return PrintingLiteraryBooks()
53.  
54.     def publish_book(self):
55.         return LiteraryBooks()
56.  
58. # 实例化工厂对象
59. it = TechnicalFactory()
60. ly = LiteraryFactory()
61.  
62. # 印刷书籍
63. it_print = it.print_book()
64. ly_print = ly.print_book()
65. # 出版书籍
66. it_publish = it.publish_book()
67. ly_publish = ly.publish_book()
  • 抽象工厂模式与工厂方法模式的区别:
    • 抽象工厂中的一个工厂对象可以负责多个不同产品对象的创建。
  • 抽象工厂的使用场景:
    • 当多个产品(步骤)集合在一起,组成产品族时
    • 对应一个产品族时,如果只想显示接口而不是实现时。

四、 建造者模式

将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示,建造者模式将所有细节都交由子类实现。需求:画人物,要求画一个人的左手、右手、左脚、右脚和身体,画一个瘦子和一个胖子。

1. 不使用设计模式

1. if __name__=='__name__':2.     print '画左手'3.     print '画右手'4.     print '画左脚'5.     print '画右脚'6.     print '画胖身体'7.  8.     print '画左手'9.     print '画右手'
10.     print '画左脚'
11.     print '画右脚'
12.     print '画瘦身体'

这样写的缺点每画一个人,都要画他的5个部位,这些部位有一些是可以重用的,所以调用起来会比较繁琐,而且客户调用的时候可能会忘记画其中一个部分,所以容易出错。
建造一个抽象的类Builder,声明画他的五个部位的方法,每画一种人,就新建一个继承Builder的类,这样新建的类就必须实现Builder的所有方法,这里主要运用了抽象方法的特性,父类定义了几个抽象的方法,子类必须要实现这些方法,否则就报错,这里解决了会漏画一个部位的问题。建造一个指挥者类Director,输入一个Builder的方法,定义一个draw的方法,把画这五个部位的方法调用都放在里面,这样调用起来就不会繁琐了。

  • Python本身不提供抽象类和接口机制,要想实现抽象类,可以借助abc模块。Abc模块是Abstract Base Class的缩写。
  • 被@abstractmethod装饰为抽象方法后,该方法不能被实例化;除非子类实现了基类的抽象方法,所以能实例化。

2. 使用设计模式

1. #encodig=utf-82. from abc import ABCMeta, abstractmethod3. class Builder():4.     __metaclass__ = ABCMeta5.     6.     @abstractmethod7.     def draw_left_arm(self):8.         pass9.
10.     @abstractmethod
11.     def draw_right_arm(self):
12.         pass
13.     
14.     @abstractmethod
15.     def draw_left_foot(self):
16.         pass
17.     
18.     @abstractmethod
19.     def draw_right_foot(self):
20.         pass
21.     
22.     @abstractmethod
23.     def draw_body(self):
24.         pass
25.     
26. class Thin(Builder): # 继承抽象类,必须实现其中定义的方法
27.     def draw_left_arm(self):
28.         print('画瘦子左手')
29.     
30.     def draw_right_arm(self):
31.         print('画瘦子右手')
32.     
33.     def draw_left_foot(self):
34.         print('画瘦子左脚')
35.     
36.     def draw_right_foot(self):
37.         print('画瘦子右脚')
38.     
39.     def draw_body(self):
40.         print('画瘦子身体')
41.         
42. class Fat(Builder): # 继承抽象类,必须实现其中定义的方法
43.     def draw_left_arm(self):
44.         print('画胖子左手')
45.     
46.     def draw_right_arm(self):
47.         print('画胖子右手')
48.     
49.     def draw_left_foot(self):
50.         print('画胖子左脚')
51.     
52.     def draw_right_foot(self):
53.         print('画胖子右脚')
54.     
55.     def draw_body(self):
56.         print('画胖子的身体')
57.         
58. class Director():
59.     def __init__(self, person):
60.         self.person = person
61.         
62.     def draw(self):
63.         self.person.draw_left_arm()
64.         self.person.draw_right_arm()
65.         self.person.draw_left_foot()
66.         self.person.draw_left_foot()
67.         self.person.draw_body()
68.         
69. if __name__ == '__main__':
70.     thin = Thin()
71.     fat = Fat()
72.     director_thin = Director(thin)
73.     director_thin.draw()
74.     director_fat = Director(fat)
75.     director_fat.draw()

建造者模式用于将一个复杂的对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

这篇关于Python面经【9】- Python设计模式专题-下卷的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/484277

相关文章

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财

Python中的Walrus运算符分析示例详解

《Python中的Walrus运算符分析示例详解》Python中的Walrus运算符(:=)是Python3.8引入的一个新特性,允许在表达式中同时赋值和返回值,它的核心作用是减少重复计算,提升代码简... 目录1. 在循环中避免重复计算2. 在条件判断中同时赋值变量3. 在列表推导式或字典推导式中简化逻辑

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息