python设计模式笔记1:创建型模式 工厂模式和抽象工厂模式
1.工厂模式
(1) 导入所需的模块( json 和 ElementTree )。
(2) 定义 JSON数据提取器类( JSONDataExtractor )。
(3) 定义 XML数据提取器类( XMLDataExtractor )。
(4) 添加工厂函数 dataextraction_factory() ,以获得正确的数据提取器类。
(5) 添加处理异常的装饰器函数 extract_data_from() 。
(6) 最终,添加 main() 函数,并使用 Python传统的命令行方式调用该函数。 main 函数的要
点如下。
尝试从 SQL文件(data/person.sq3)中提取数据,以展示异常处理的方式。
从 JSON文件中提取数据并解析出结果。
从 XML文件中提取数据并解析出结果。
测试文件
movies.json
[{"title":"After Dark in Central Park","year":1900, "director":null, "cast":null, "genre":null},{"title":"Boarding School Girls' Pajama Parade","year":1900, "director":null, "cast":null, "genre":null},{"title":"Buffalo Bill's Wild West Parad","year":1900, "director":null, "cast":null, "genre":null},{"title":"Caught","year":1900, "director":null, "cast":null, "genre":null},{"title":"Clowns Spinning Hats","year":1900, "director":null, "cast":null, "genre":null},
{"title":"Capture of Boer Battery by British","year":1900, "director":"James H. White", "cast":null, "genre":"Short documentary"},{"title":"The Enchanted Drawing","year":1900, "director":"J. Stuart Blackton", "cast":null,"genre":null},{"title":"Family Troubles","year":1900,"director":null, "cast":null, "genre":null},{"title":"Feeding Sea Lions","year":1900,"director":null, "cast":"Paul Boyton", "genre":null}]
persons.xml
<persons> <person> <firstName>John</firstName> <lastName>Smith</lastName> <age>25</age> <address> <streetAddress>21 2nd Street</streetAddress> <city>New York</city> <state>NY</state> <postalCode>10021</postalCode> </address> <phoneNumbers> <phoneNumber type="home">212 555-1234</phoneNumber> <phoneNumber type="fax">646 555-4567</phoneNumber> </phoneNumbers> <gender> <type>male</type> </gender> </person> <person> <firstName>Jimy</firstName> <lastName>Liar</lastName> <age>19</age> <address> <streetAddress>18 2nd Street</streetAddress> <city>New York</city> <state>NY</state> <postalCode>10021</postalCode> </address> <phoneNumbers> <phoneNumber type="home">212 555-1234</phoneNumber> </phoneNumbers> <gender> <type>male</type> </gender> </person> <person> <firstName>Patty</firstName> <lastName>Liar</lastName> <age>20</age> <address> <streetAddress>18 2nd Street</streetAddress> <city>New York</city> <state>NY</state> <postalCode>10021</postalCode> </address> <phoneNumbers> <phoneNumber type="home">212 555-1234</phoneNumber> <phoneNumber type="mobile">001 452-8819</phoneNumber> </phoneNumbers> <gender> <type>female</type> </gender> </person>
</persons>
chapter01/mycode/factory_method.py

""" https://zhuanlan.zhihu.com/p/64487092 python的@property是python的一种装饰器,是用来修饰方法的。 创建只读属性 @property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改 parsed_data 作为属性 """
完整代码
def extract_data_from(filepath):factory_obj = Nonetry:factory_obj = dataextraction_factory(filepath)except ValueError as e:print(e)return factory_objdef main():# 异常测试sqlite_factory=extract_data_from('../data/person.sq3')print()# Cannot extract data from ../data/person.sq3json_factory = extract_data_from('../data/movies.json')json_data=json_factory.parsed_dataprint(f"found:{len(json_data) } movices")for movie in json_data:print(f"Title:{movie['title']}")year = movie['year']if year:print(f"Year: {year}")director = movie['director']if director:print(f"Director: {director}")genre = movie['genre']if genre:print(f"Genre: {genre}")print()"""xml 解析使用工厂方法处理 XML 文件。Xpath 用于寻找所有姓为 Liar 的person 元素(使用 liars = xml_data.findall(f".//person[lastName='Liar']") )。对于每一个匹配的人,将展示其基本姓名与电话号码信息"""xml_factory = extract_data_from('../data/person.xml')xml_data = xml_factory.parsed_dataliars=xml_data.findall(f".//person[lastName='Liar']")print(f'found:{len(liars)} persons')for liar in liars:firstname = liar.find('firstName').textprint(f'first name: {firstname}')lastname = liar.find('lastName').textprint(f'last name: {lastname}')[print(f"phone number ({p.attrib['type']}):", p.text)for p in liar.find('phoneNumbers')]print()
if __name__ == '__main__':main()
虽然 JSONDataExtractor 和 XMLDataExtractor 有相同的接口,但是它们处理
parsed_data() 返回值的方式并不一致。每个数据解析器必须与不同的 Python代码相配套。
2.抽象工厂模式
抽象工厂模式是一种一般化的工厂方法模式,它提供了相同的好处:使跟踪对象创建更
容易,将对象的创建与使用解耦,并赋予你提升应用内存使用率与性能的可能性。
如何知道该使用工厂方法还是抽象工厂?
通常从
简单的工厂方法开始。如果发现应用程序需要许多工厂方法,且将这些方法组合起来创建一系列
对象是有意义的,那么就使用抽象工厂。
典型的例子是能够在用户使用应用程序时为其更改应用程序的外观(例如,Apple风格界面、Windows风格界面等),而无须终止应用再重新启动。
例子:创建一个游戏
希望至少包括两款游戏:一款儿童游戏,一款成人游戏。我们将根据用户的输入,在运行时决定创建和启动哪款游戏。抽象工厂会负责游戏创建的部分。
游戏: FrogWorld FrogWorld 适应抽象工厂 ,主要任务是创建游戏注解和障碍物 保持创建方 法的独立性及名称的通用性(例如, make_character() 和 make_obstacle() ),我们将能动 态地更改处于激活状态的工厂(进而改变处于激活状态的游戏),而不需要修改任何代码。在静 态类型语言中,抽象工厂是一个带有空方法的抽象类/接口,但是在 Python 中,这是不必要的, 因为类型是在运行时检查的( j.mp/ginstromdp )。
游戏1:
FrogWorld。男主角是一只喜欢吃虫子的青蛙。每个
主角都需要一个好的名字,在我们的例子中,这个名字是由用户在运行时给出的。 interact_
with() 方法用于描述青蛙与障碍物(例如,虫子、谜题和其他青蛙)的交互。
"""
游戏: FrogWorld
FrogWorld 适应额抽象工厂 ,主要任务是创建游戏注解和障碍物
保持创建方
法的独立性及名称的通用性(例如, make_character() 和 make_obstacle() ),我们将能动
态地更改处于激活状态的工厂(进而改变处于激活状态的游戏),而不需要修改任何代码。在静
态类型语言中,抽象工厂是一个带有空方法的抽象类/接口,但是在 Python 中,这是不必要的,
因为类型是在运行时检查的( j.mp/ginstromdp )。
"""class Frog:def __init__(self, name):self.name = namedef __str__(self):return self.namedef interact_with(self, obstacle):act = obstacle.action()msg = f'{self} the Frog encounters {obstacle} and {act}!'print(msg)# 虫子
class Bug:def __init__(self):passdef __str__(self):return 'a bug'def action(self):return 'eats it 'class FrogWorld:def __init__(self, name):print(self)self.player_name = namedef __str__(self):return '\n\n\t------ Frog World -------'def make_character(self):return Frog(self.player_name)def make_obstacle(self):return Bug()
游戏2:
名为 WizardWorld 的游戏也是类似的。唯一的区别是,巫师与怪物(如 orks 兽人)战斗,
而不是吃虫子。
FrogWorld 游戏定义Frog 和Bug类
(1) 为FrogWorld 游戏定义Frog 和Bug 类
(2)添加FrogWold 类,在其中使用Frog 和Bug 类
(3)为WizardWold 游戏定义wizrd 和Ork 类
(4) 添加WizardWold 类,在其中使用Wizard 类和Ork 类
(5) 定义GameEnviroment类
(6)添加validate_age() 函数
(7) 使用main()函数
获取用户输入的姓名和年龄
根据用户的 年龄决定使用的游戏
实例化正确的游戏类,然后实例化GameEnviroment类
调用enviroment对象的play() 方法 玩游戏
完整代码
chapter01/mycode/abstract_factory.py
"""
游戏: FrogWorld
FrogWorld 适应额抽象工厂 ,主要任务是创建游戏注解和障碍物
保持创建方
法的独立性及名称的通用性(例如, make_character() 和 make_obstacle() ),我们将能动
态地更改处于激活状态的工厂(进而改变处于激活状态的游戏),而不需要修改任何代码。在静
态类型语言中,抽象工厂是一个带有空方法的抽象类/接口,但是在 Python 中,这是不必要的,
因为类型是在运行时检查的( j.mp/ginstromdp )。
"""class Frog:def __init__(self, name):self.name = namedef __str__(self):return self.namedef interact_with(self, obstacle):act = obstacle.action()msg = f'{self} the Frog encounters {obstacle} and {act}!'print(msg)# 虫子
class Bug:def __init__(self):passdef __str__(self):return 'a bug'def action(self):return 'eats it 'class FrogWorld:def __init__(self, name):print(self)self.player_name = namedef __str__(self):return '\n\n\t------ Frog World -------'def make_character(self):return Frog(self.player_name)def make_obstacle(self):return Bug()# 巫师
class Wizard:def __init__(self, name):self.name = namedef __str__(self):return self.namedef interact_with(self, obstacle):act = obstacle.action()msg = f'{self} the Wizard battles against {obstacle}and {act}!'print(msg)# 怪物
class Ork:def __str__(self):return 'an evil ork'def action(self):return 'kills it'class WizardWorld:def __init__(self, name):print(self)self.player_name = namedef __str__(self):return '\n\n\t------ Wizard World -------'def make_character(self):return Wizard(self.player_name)def make_obstacle(self):return Ork()"""
GameEnvironment 类是我们游戏的主入口。它接受一个工厂作为输入,并使用它来创建游
戏世界。 play() 方法初始化主角与障碍物之间的交互"""# 游戏的入口 接收一个工厂作为输入,并且使用它创建游戏世界 paly() 方法初始化主角与障碍物之间的交互
class GameEnvironment:def __init__(self, facotry):self.hero = facotry.make_character()self.abstacle = facotry.make_obstacle()def play(self):self.hero.interact_with(self.abstacle)def validate_age(name):try:age = input(f'Welcome {name}. How old are you? ')age = int(age)except ValueError as err:print(f"Age {age} is invalid, please try again...")return (False, age)return (True, age)def main():name = input("Hello,what's your name?")valid_input = Falsewhile not valid_input:valid_input, age = validate_age(name)game = FrogWorld if age < 18 else WizardWorldenvironment = GameEnvironment(game(name))environment.play()if __name__ == '__main__':main()
运行结果:
Hello,what's your name? aa
Welcome aa. How old are you? 12------ Frog World -------aa the Frog encounters a bug and eats it !
Hello,what's your name?bb
Welcome bb. How old are you? 19------ Wizard World -------
bb the Wizard battles against an evil orkand kills it!Process finished with exit code 0
相关文章:
python设计模式笔记1:创建型模式 工厂模式和抽象工厂模式
1.工厂模式 (1) 导入所需的模块( json 和 ElementTree )。 (2) 定义 JSON数据提取器类( JSONDataExtractor )。 (3) 定义 XML数据提取器类( XMLDataExtractor )。 (4) 添加工厂函数 dataextraction_factor…...
第五章 I/O管理 一、I/O设备的基本概念和分类
目录 一、什么是I/O设备 1、定义: 2、按特性分类: 3、按传输速率分类: 4、按信息交换的方式分类: 二、总结 一、什么是I/O设备 1、定义: I/O设备就是可以将数据输入到计算机,或者可以接收计算机输出…...
vue3动态引入图片(:src)
vite 官方默认的配置,如果资源文件在assets文件夹打包后会把图片名加上 hash值,但是直接通过 :src"imgSrc"方式引入并不会在打包的时候解析,导致开发环境可以正常引入,打包后却不能显示的问题 实际上我们不希望资源文…...
Android-登录注册页面(第三次作业)
第三次作业 - 登录注册页面 题目要求 嵌套布局。使用线性布局的嵌套结构,实现登录注册的页面。(例4-3) 创建空的Activity 项目结构树如下图所示: 注意:MainActivity.java文件并为有任何操作,主要功能集中…...
[论文精读]How Powerful are Graph Neural Networks?
论文原文:[1810.00826] How Powerful are Graph Neural Networks? (arxiv.org) 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记&#x…...
Redis实现分布式锁之----超时和失效(非原子性)问题----解决方案
Redis实现分布式锁之----超时和失效(非原子性)问题----解决方案 超时和失效(非原子性)问题 原子性问题:上锁时存入线程名称,删除时要先判断锁内的名称是不是自己的,是再删除,但是后…...
Android使用Hilt依赖注入,让人看不懂你代码
前言 之前接手的一个项目里有些代码看得云里雾里的,找了半天没有找到对象创建的地方,后来才发现原来使用了Hilt进行了依赖注入。Hilt相比Dagger虽然已经比较简洁,但对初学者来说还是有些门槛,并且网上的许多文章都是搬自官网&…...
ZYNQ连载01-ZYNQ介绍
ZYNQ连载01-ZYNQ介绍 1. ZYNQ 参考文档:《ug585-zynq-7000-trm.pdf》 ZYNQ分为PS和PL两大部分,PS即ARM,PL即FPGA,PL作为PS的外设。 2. 方案 ZYNQ7020为双核A9架构,多核处理器常用的运行模式为AMP(非对称多处理)和…...
第十节——Vue组件
一、什么是组件 组件(Component)是vue.js中很强大的一个功能,可以将一些可重用的代码进行封重用。 所有的Vue 组件同时也是Vue 的实例,可以接受使用相同的选项对象和提供相同的生命周期钩子。 一句话概括:组件就是可以扩展HTML元素ÿ…...
Redis(01)| 数据结构
这里写自定义目录标题 Redis 速度快的原因除了它是内存数据库,使得所有的操作都在内存上进行之外,还有一个重要因素,它实现的数据结构,使得我们对数据进行增删查改操作时,Redis 能高效的处理。 因此,这次我…...
SpringBoot工程启动时自动创建数据库、数据表
文章目录 一,序二,自动创建数据库1. 数据源配置2. 修改支持数据库创建 三,自动创建数据库表以及数据1. 准备DDL、DML语句1.)典型DDL语句2.)典型DML语句 2. 设置初始化参数 四、源码传送 一,序 针对Java工程…...
Uni-app智慧工地可视化信息平台源码
智慧工地的核心是数字化,它通过传感器、监控设备、智能终端等技术手段,实现对工地各个环节的实时数据采集和传输,如环境温度、湿度、噪音等数据信息,将数据汇集到云端进行处理和分析,生成各种报表、图表和预警信息&…...
计算机网络重点概念整理-第五章 传输层【期末复习|考研复习】
第五章 传输层 【期末复习|考研复习】 计算机网络系列文章传送门: 第一章 计算机网络概述 第二章 物理层 第三章 数据链路层 第四章 网络层 第五章 传输层 第六章 应用层 第七章 网络安全 计算机网络整理-简称&缩写 文章目录 第五章 传输层 【期末复习|考研复习…...
Java毕业设计 SpringBoot 新能源充电桩管理系统
Java毕业设计 SpringBoot 新能源充电桩管理系统 SpringBoot 新能源充电桩管理系统 功能介绍 管理员 登录 验证码 注册 系统用户管理 普通用户管理 通知公告管理 留言管理 充电站管理 充电桩管理 充电桩预约 充电管理 订单管理 修改密码 普通用户 登录 修改个人资料 通知公告…...
JNI接口
NewStringUTF和NewString接口测试 打开输入法“显示表情与符号” 右键,拷贝字符简介 🍌 香蕉 Unicode: U1F34C,UTF-8: F0 9F 8D 8C unicode码 🍌 \U0001f34c utf-8编码为0xf09f8d8c,结合char或char8_t的长度&…...
国内好用的免费ai软件
国内就只推荐几个大厂,基本感受都差不多 百度文心一言 百度研发的知识增强大语言模型,能够与人对话互动,回答问题,协助创作,高效便捷地帮助人们获取信息、知识和灵感。 地址:文心一言 (baidu.com) 阿里通…...
MAC缓解WebUI提示词反推
当前环境信息: 在mac上安装好stable diffusion后,能做图片生成了之后,遇到一些图片需要做提示词反推,这个时候需要下载一个插件,参考: https://gitcode.net/ranting8323/stable-diffusion-webui-wd14-tagg…...
【设计模式之原型模式 】– C++
5. 原型模式 – 复制粘贴,一摸一样 简介 原型模式(Prototype Pattern)是一种创建型设计模式,其主要目的是通过复制现有对象来创建新的对象,而无需从头开始构建。 使用场景 它通常用于以下情况: 当一个系统…...
Flask路由机制分析之二
一、前言 上篇 《Flask 路由机制分析之一》主要讲了Python函数的特性以及装饰器的基本概念,这节我们具体分析一下路由内部机制,Flask路由依赖于werkzegu的routing模块来实现。 二、werkzegu的routing模块介绍 Werkzegu库的routing模块主要功能在于URL…...
vue中如何获取当时时间时分秒
在 Vue 中可以使用 JavaScript 中的 Date 对象来获取当前时间,然后使用 Vue 中的数据绑定将时间显示在页面上。 <template><div><p>当前时间:{{ time }}</p></div> </template><script> export default {dat…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
