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绘制蛇年春节祝福艺术图

《使用Python绘制蛇年春节祝福艺术图》:本文主要介绍如何使用Python的Matplotlib库绘制一幅富有创意的“蛇年有福”艺术图,这幅图结合了数字,蛇形,花朵等装饰,需要的可以参考下... 目录1. 绘图的基本概念2. 准备工作3. 实现代码解析3.1 设置绘图画布3.2 绘制数字“2025”3.3

python使用watchdog实现文件资源监控

《python使用watchdog实现文件资源监控》watchdog支持跨平台文件资源监控,可以检测指定文件夹下文件及文件夹变动,下面我们来看看Python如何使用watchdog实现文件资源监控吧... python文件监控库watchdogs简介随着Python在各种应用领域中的广泛使用,其生态环境也

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

python 字典d[k]中key不存在的解决方案

《python字典d[k]中key不存在的解决方案》本文主要介绍了在Python中处理字典键不存在时获取默认值的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,... 目录defaultdict:处理找不到的键的一个选择特殊方法__missing__有时候为了方便起见,

使用Python绘制可爱的招财猫

《使用Python绘制可爱的招财猫》招财猫,也被称为“幸运猫”,是一种象征财富和好运的吉祥物,经常出现在亚洲文化的商店、餐厅和家庭中,今天,我将带你用Python和matplotlib库从零开始绘制一... 目录1. 为什么选择用 python 绘制?2. 绘图的基本概念3. 实现代码解析3.1 设置绘图画

Python pyinstaller实现图形化打包工具

《Pythonpyinstaller实现图形化打包工具》:本文主要介绍一个使用PythonPYQT5制作的关于pyinstaller打包工具,代替传统的cmd黑窗口模式打包页面,实现更快捷方便的... 目录1.简介2.运行效果3.相关源码1.简介一个使用python PYQT5制作的关于pyinstall

使用Python实现大文件切片上传及断点续传的方法

《使用Python实现大文件切片上传及断点续传的方法》本文介绍了使用Python实现大文件切片上传及断点续传的方法,包括功能模块划分(获取上传文件接口状态、临时文件夹状态信息、切片上传、切片合并)、整... 目录概要整体架构流程技术细节获取上传文件状态接口获取临时文件夹状态信息接口切片上传功能文件合并功能小

python实现自动登录12306自动抢票功能

《python实现自动登录12306自动抢票功能》随着互联网技术的发展,越来越多的人选择通过网络平台购票,特别是在中国,12306作为官方火车票预订平台,承担了巨大的访问量,对于热门线路或者节假日出行... 目录一、遇到的问题?二、改进三、进阶–展望总结一、遇到的问题?1.url-正确的表头:就是首先ur

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主