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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/154797.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Docker 内核详解】cgroups 资源限制(二):组织结构与基本规则、子系统简介

cgroups 资源限制&#xff08;二&#xff09;&#xff1a;组织结构与基本规则、子系统简介 1.组织结构与基本规则2.子系统简介 1.组织结构与基本规则 在之前的博客已经介绍过&#xff0c;传统的 Unix 任务管理&#xff0c;实际上是先启动 init 任务作为根节点&#xff0c;再由…

基于RFID技术的智能医疗柜管理系统解决方案

一、行业背景 当前&#xff0c;医疗机构面临着药物过期、召回、空货架、放错产品和库存缺失等问题&#xff0c;这些问题导致医院项目效率低下&#xff0c;患者护理不足&#xff0c;医护人员备受困扰。为了应对全球医疗体系面临的压力&#xff0c;医疗保健机构急需寻找新技术来…

Xubuntu16.04系统中create_ap开启5G网络的踩坑记录

Xubuntu16.04系统中安装create_ap创建无线AP&#xff1a; https://blog.csdn.net/qq_45445740/article/details/133972642?spm1001.2014.3001.5501 目录 1.create_ap.conf 配置文件解析2.关于信号强度和延时2.1 信号强度2.2 信号延时2.3 网络延时测试工具推荐——PingPlotter …

【RTOS学习】CubeMX对FreeRTOS的适配

&#x1f431;作者&#xff1a;一只大喵咪1201 &#x1f431;专栏&#xff1a;《RTOS学习》 &#x1f525;格言&#xff1a;你只管努力&#xff0c;剩下的交给时间&#xff01; 经过前面的学习&#xff0c;现在我已经对FreeRTOS有了一个初步的认识&#xff0c;而且也可以使用F…

易基因:ChIP-seq等揭示BRWD3调控KDM5活性以维持H3K4甲基化水平的表观机制|PNAS

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 组蛋白修饰对调控染色质结构和基因表达至关重要&#xff0c;组蛋白修饰失调可能导致疾病状态和癌症。染色质结合蛋白BRWD3&#xff08;Bromodomain and WD repeat-containing protein 3&…

PHP在线客服系统平台系统源码+完全开源 带完整的搭建教程

在线客服系统已经成为企业与用户进行实时沟通的重要工具。PHP作为一种流行的服务器端脚本语言&#xff0c;具有高效、稳定和易用性等优点&#xff0c;因此被广泛应用于在线客服系统的开发。今天罗峰来给大家介绍一款PHP在线客服系统平台系统源码&#xff0c;源码完全开源&#…

低功耗设计-ir drop的signoff corner怎么选择?

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 相关文章链接: Multi Voltage Flow笔记 有几个方向&#xff0c;看公司需求吧 1.功耗最差的&#xff1b; 2.tt的&#xff08;tt85 是比较接近芯片真实工作情况的&#xff09…

MySQL数据库操作、表操作和常用数据类型

1、数据库操作 1.1 创建数据库 语法&#xff1a;CREATE DATABASE [IF NOT EXISTS] 数据库名 charset utf8;&#xff08;注意字母不区分大小写&#xff0c;分号为英文输入法&#xff09;&#xff0c;[ ]为可选项&#xff0c;意思为如果系统没有想要创建&#xff08;数据库名&am…

万字解析设计模式之原型模式与建造者模式

一、原型模式 1.1概述 原型模式是一种创建型设计模式&#xff0c;其目的是使用已有对象作为原型来创建新的对象。原型模式的核心是克隆&#xff0c;即通过复制已有对象来创建新对象&#xff0c;而不是通过创建新对象的过程中独立地分配和初始化所有需要的资源。这种方式可以节…

C# “依赖注入” 中的 “三种生命周期”

&#x1f680;简介 依赖注入&#xff08;Dependency Injection&#xff0c;简称DI&#xff09;是一种实现控制反转&#xff08;IoC&#xff09;的技术&#xff0c;用于减少代码之间的耦合度。通过依赖注入&#xff0c;一个类可以从外部获取其依赖的对象&#xff0c;而不是自己…

java解决修改图片尺寸,压缩图片后出现背景变黑,图片字体模糊问题

将以下数学公式的图片使用Hutool提供的图片工具类改变尺寸 代码如下: package com.jason.common.file.word;import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil;import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage;…

同城门户同城分类信息网站源码discuz插件+pc端+小程序端+49款插件

同城分类信息 同城好店 同城合伙人 同城招聘 同城卡 同城活动 同城优惠抢购 同城商城 同城头条 同城抽奖 同城拼团 同城砍价 同城电话本 同城认证 同城签到 同城拼车 同城红包 同城子站点 同城相亲 同城交友 同城小程序 代码逻辑清晰,文件规划统一明了&#xff0c;非常不错的&…