python设计模式之抽象工厂模式详解
作者:Spuer_Tiger 发布时间:2023-06-11 22:15:51
抽象工厂模式(Abstract Factory Pattern):属于创建型模式,它提供了一种创建对象的最佳方式。在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类,每个生成的工厂都能按照工厂模式提供对象。
意图: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。
主要解决: 主要解决接口选择的问题。
何时使用: 系统的产品有多于一个的产品族,而系统只消费其中某一族的产品。
如何解决: 在一个产品族里面,定义多个产品。
关键代码: 在一个工厂里聚合多个同类产品。
优点: 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。抽象工厂模式相较于工厂模式,划分更加明确清晰,面对复杂的生产任务,管理和生产性能会更加高效。
缺点: 产品族扩展非常困难,要增加一整个系列的某一产品。
注意事项: 产品族难扩展,产品等级易扩展。
应用实例: 对于一个生产水果的工厂,工厂模式主要针对一种水果创建一个涵盖与该水果相关所有业务的工厂(例如:葡萄的运输、保存、加工、包装、售卖等相关业务全部被该工厂承包);而抽象工厂模式主要针对生产其中的某一环节进行创建相应的工厂(例如:运输工厂负责管理所有水果的运输,售卖工厂负责管理所有水果的价格和售卖,库存工厂负责管理所有水果的库存计数等)。
那我们来一起使用抽象工厂模式,构建一个购买水果的收银小项目吧!(づ。◕ᴗᴗ◕。)づ
实现的思路:
项目的主体包含6个部分:消费者(买水果的人),水果工厂(卖水果的人),水果工厂旗下的子工厂(品种工厂、价格工厂、包装工厂、称重工厂消费者主要向水果工厂传达“购买需求”的相关信息(水果的种类、包装、重量等…);水果工厂主要针对消费者的不同“购买需求”将任务分派给子工厂进行执行;品种工厂负责管理水果的种类,价格工厂负责管理水果的价格,称重工厂负责水果的称重,包装工厂负责水果的包装方式。
项目的UML用例图如下:
实现的代码如下:
class FruitClass:
# 品种工厂
def get_name(self, name_index):
if name_index == 0:
name_object = OrangeClass()
elif name_index == 1:
name_object = Hami_MelonClass()
elif name_index == 2:
name_object = GrapeClass()
else:
name_object = None
return name_object
class OrangeClass:
# 橘子类
def __init__(self):
self.name = "橘子"
def print_name(self):
print("您购买的水果为:%s" % self.name)
class Hami_MelonClass:
# 哈密瓜类
def __init__(self):
self.name = "哈密瓜"
def print_name(self):
print("您购买的水果为:%s" % self.name)
class GrapeClass:
# 葡萄类
def __init__(self):
self.name = "葡萄"
def print_name(self):
print("您购买的水果为:%s" % self.name)
class FruitWeight:
# 称重工厂
def __init__(self, weight):
self.weight = float(weight)
def print_weight(self):
print("该水果的重量为:%.2f千克" % self.weight)
class FruitPrice:
# 价格工厂
def get_price(self, name_index, variety):
if name_index == 0:
price_object = OrangePrice(variety)
elif name_index == 1:
price_object = Hami_MelonPrice()
elif name_index == 2:
price_object = GrapePrice()
else:
price_object = None
return price_object
class OrangePrice:
# 橘子价格类
def __init__(self, variety):
self.variety = variety
if self.variety == 1:
self.price = 8.5
else:
self.price = 11.0
def print_price(self):
print("该水果的单价为:%.2f元/千克" % self.price)
class Hami_MelonPrice:
# 哈密瓜价格类
def __init__(self):
self.price = 24.3
def print_price(self):
print("该水果的价格为:%.2f元/千克" % self.price)
class GrapePrice:
# 葡萄价格类
def __init__(self):
self.price = 16.2
def print_price(self):
print("该水果的价格为:%.2f元/千克" % self.price)
return self.price
class FruitPack:
# 包装工厂
def __init__(self, pack):
if pack == 1:
self.pack = "散称"
else:
self.pack = "盒装"
def print_pack(self):
print("该水果的打包方式为:%s" % self.pack)
class FruitFactory:
def __init__(self, name_index, weight, variety, pack):
# 任务的分配,品种、重量、价格、包装方式
self.name_object = FruitClass().get_name(name_index)
self.weight_object = FruitWeight(weight)
self.price_object = FruitPrice().get_price(name_index, variety)
self.pack_object = FruitPack(pack)
def print_purchase(self):
# 计算购买的金额
money = self.price_object.price * self.weight_object.weight
print("需要支付的金额共计为:%.2f元" % money)
def show_info(self):
# 展示最终的购买信息
self.name_object.print_name()
self.weight_object.print_weight()
self.price_object.print_price()
self.pack_object.print_pack()
self.print_purchase()
print("-*-" * 20)
class Consumer:
# 消费者类
def __init__(self):
print("-*-" * 20)
# 输入原始的“购买需求”信息
self.name = input("请输入你要购买的水果名称:0.橘子 1.哈密瓜 2.葡萄\n")
self.weight = input("请输入你要购买水果的重量(kg):\n")
self.variety = input("如果您购买橘子,我们有2种橘子:0.不买橘子 1.甘橘 2.砂糖橘\n")
self.pack = input("请您选择该水果的包装方式:1.散称 2.盒装\n")
print("-*-" * 20)
def request(self):
# 返回相关的购买信息
return self.name, self.weight, self.variety, self.pack
if __name__ == '__main__':
# 创建顾客
buyer = Consumer()
# 拿到顾客的购买信息
buy_info = buyer.request()
# 使用水果工厂,传达指令至旗下的子工厂并执行购买操作
buy_res = FruitFactory(int(buy_info[0]), int(buy_info[1]), int(buy_info[2]), int(buy_info[3]))
# 购买信息的展示
buy_res.show_info()
相关的测试用例:
本文关于设计模式的讲解思想,参考链接:抽象工厂模式
如果有对python类的创建和继承等用法还不熟悉的小伙伴,请参考这篇博客: python类的继承
来源:https://blog.csdn.net/acceptedday/article/details/117906413
猜你喜欢
- Windows环境: (1)离线安装 首先在线搜索并下载你需要的第三方库:网址https
- Python装饰器用法Python的装饰器是个好东西,它能干很多事情。但对于新手,它看起来似乎没那么简单。但事实上,装饰器本身也只是个函数。
- 在JAVA WEB应用中,如何获取servlet请求中的参数,并传递给跳转的JSP页面?例如访问http://localhost:8088/
- 刚刚换用windows7 64位旗舰版,使用其自带的iis7作为调试工具,今天调试一个ASP+ACCESS的网站的时候遇到了“ADODB.C
- 你可能会遇到这样的要求,一个脚本,只允许有一个实例。在python中,为了实现这个需求,可以引入fcntl模块对文件加一个排他锁,这样一来,
- 目录前言 字符串都有哪些操作?第一类 判断识别字符串第二类 字符串编辑的操作第三类:字符串跟字节串的互转总结前言今天我们说了字符串
- 区别:xx:公有变量,所有对象都可以访问;xxx:双下划线代表着是系统定义的名字。__xxx:双前置下划线,避免与子类中的属性命名冲突,无法
- 本人就职于一个本地门户网站,每天网站上的天气都得更新。久而久之感到相当麻烦,于是写了一个定时的新闻小偷,帖出来大家参考一下系统
- 京东商品详细的请求处理,是先显示html,然后再ajax请求处理显示价格。1.可以运行js,并解析之后得到的html2.模拟js请求,得到价
- 一、怎么样取得最新版本的MySQL?要安装MySQL,首先要当然要取得它的最新版本,虽然大家都知道在FreeBSD的Packages中可以找
- 原来的题目设想为界面视觉效果的统一性,但是“统一”这个词似乎有点敏感,怕触动萌点无数,而我也无意去设定一个什么什么的统一性来侃侃而谈,极为专
- 一、注释1.#单行注释2."""多行注释"""3.pycharm多行注释快捷键:
- 功能说明: 滑动展开/收缩广告效果,可指定:广告完全展开时的停留时间,最大高度。兼容浏览器:IE5.0+、FF1.06+、Opera8.0+
- ISNULL 使用指定的替换值替换 NULL。 &nb
- oblog 推出了4.0的最新版本,这个不是重点,重点是4.0的版本中附带了xml-rpc支持。oblog的支持代表着大量的国内blog站点
- 切片从list或tuple中取部分元素。list = [1, 2, 3, 4]list[0 : 3] # [1, 2, 3]list[-2
- 功能1: 爬取西拉ip代理官网上的代理ip环境:python3.8+pycharm库:requests,lxml浏览器:谷歌IP地址:htt
- <style type="text/css"> <!-- body,td,th {
- 如何用ASP建立Index Server查询对象并为其参数赋值?我们有两个方法可以做到这一点。一个方法是利用Index Server que
- 说明: a、以下字符中数据库名forum,数据库服务器名WWW-2443D34E558\SQL2005(或者127.0.0.1) b、查看s