工厂模式(Factory Pattern):属于创建型模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们 在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象 。
意图: 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。
主要解决: 主要解决接口选择的问题。
何时使用: 我们明确地计划不同条件下创建不同实例时。
如何解决: 让其子类实现工厂接口。
关键代码: 创建过程在其子类执行。
优点: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。
缺点: 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
注意事项: 作为一种创建类模式,在任何需要生成复杂对象的地方,都可以使用工厂方法模式。有一点需要注意的地方就是复杂对象适合使用工厂模式,而简单对象,特别是只需要通过 new 就可以完成创建的对象,无需使用工厂模式。如果使用工厂模式,就需要引入一个工厂类,会增加系统的复杂度。
应用实例:我想买一些水果(橘子、哈密瓜和葡萄),我可以直接从水果工厂里面购买,但是我不需要知道这些水果的产地是哪里的,它们是如何运输和包装的,以及水果工厂的相关流水线是如何运作的。
那我们来一起看看如何使用工厂模式,实现一个购买不同水果的小项目?(づ。◕ᴗᴗ◕。)づ
实现的思路:
- 项目的主体包含3个部分:
消费者(买水果的人),水果工厂(卖水果的人),水果大类(实现隐藏的工厂内部细节)
消费者主要向水果工厂传达“购买需求”的相关信息(水果的种类、包装、重量等...);
水果工厂主要针对消费者的不同“购买需求”将调用不同的水果大类中的子类方法;
水果大类主要划分为各种小类,针对每一类水果有独特的设计实现细节。
项目的UML用例图如下:
实现的代码如下:
class Fruit:
# 水果大类
def __init__(self, name, weight):
self.name = name
self.weight = weight
self.price = None
# 计算购买金额的抽象接口
def purchase(self):
pass
# 展示购买信息的抽象接口
def show(self):
pass
class Orange(Fruit):
# 橘子类
def __init__(self, name, weight, variety):
Fruit.__init__(self, name, weight)
# 不同的橘子类型,价格不同
if variety == 1:
self.price = 8.5
else:
self.price = 11.0
# 设定购买的橘子的类型
self.variety = variety
def purchase(self):
money = self.price * self.weight
return money
def show(self):
money = self.purchase()
print("您购买的水果:%s,单价为:%s(千克/元),重量为:%f千克\n需要支付的金额共计为:%f元" %
(self.name, self.price, self.weight, money))
class Hami_Melon(Fruit):
# 哈密瓜类
def __init__(self, name, weight):
Fruit.__init__(self, name, weight)
# 设定哈密瓜的单价
self.price = 24.3
def purchase(self):
money = self.price * self.weight
return money
def show(self):
money = self.purchase()
print("您购买的水果:%s,单价为:%s(千克/元),重量为:%f千克\n需要支付的金额共计为:%f元" %
(self.name, self.price, self.weight, money))
class Grape(Fruit):
# 葡萄类
def __init__(self, name, weight, pack):
Fruit.__init__(self, name, weight)
# 设定葡萄的单价
self.price = 16.2
# 设定葡萄的包装方式
self.pack = pack
def purchase(self):
money = self.price * self.weight
return money
def show(self):
money = self.purchase()
print("您购买的水果:%s,单价为:%s(千克/元),重量为:%f千克\n需要支付的金额共计为:%f元" %
(self.name, self.price, self.weight, money))
class FruitFactory:
# 水果工厂类
def get_info(self, name, weight, variety, pack):
weight = float(weight)
variety, pack = int(variety), int(pack)
if variety == 0 and pack == 0:
new_object = Hami_Melon(name, weight)
return new_object
elif variety > 0 and pack == 0:
new_object = Orange(name, weight, variety)
return new_object
elif variety == 0 and pack > 0:
new_object = Orange(name, weight, pack)
return new_object
else:
return None
class Consumer:
# 消费者类
def __init__(self):
# 输入原始的“购买需求”信息
self.name = input("请输入你要购买的水果名称:orange / hami_Melon / grape\n")
self.weight = input("请输入你要购买水果的重量(kg):\n")
self.variety = input("如果您购买橘子,我们有2种橘子:0.不买橘子 1.甘橘 2.砂糖橘\n")
self.pack = input("如果您购买葡萄,有2中包装方式:0.不买葡萄 1.散称 2.盒装\n")
def request(self):
# 返回相关的购买信息
return self.name, self.weight, self.variety, self.pack
if __name__ == '__main__':
# 创建顾客
buyer = Consumer()
# 拿到顾客的购买信息
buy_info = buyer.request()
# 使用水果工厂,传达指令至水果大类并执行购买操作
buy_res = FruitFactory().get_info(buy_info[0], buy_info[1], buy_info[2], buy_info[3])
# 购买信息的展示
buy_res.show()
相关的测试用例:
本文关于设计模式的讲解思想,参考链接:抽象工厂模式
如果有对python类的创建和继承等用法还不熟悉的小伙伴,请参考这篇博客: python类的继承