Python 设计模式 — 创建型模式 — 工厂模式
Posted 范桂飓
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python 设计模式 — 创建型模式 — 工厂模式相关的知识,希望对你有一定的参考价值。
目录
文章目录
工厂模式(Factory Pattern)
工厂模式(Factory Pattern),提供了一种实例化(创建)对象的最佳方式。
在工厂模式中,首先定义了一个抽象的工厂类(class Factory),并且在该工厂类中定义了提供了一个通用的、用于实例化对象的 Interface(接口)函数。然后当 Client 想要实例化某个具体的类的对象时,只需要将需求告诉工厂类即可,由工厂类按需求去完成对象的实例化并返回。而 Client 作为调用者,则无需知道对象实例化的任何细节,这意味着任意的 Client 都无需要考虑根据对象的实例化细节来调整自身的代码。
例如:当我们需要购买一批电脑,只要把我们的需求告诉电脑工厂,电脑工厂就会帮我们把这批电脑做好,而不用我们自己去做这个电脑的,也不用我们自己去知道这个电脑是怎么做出来的,这就是工厂模式。
工厂模式带来的好处就是帮助我们把对象的实例化部分抽取了出来,目的是降低系统中代码耦合度,并且增强了系统的扩展性。是一种解耦思想的实践。
应用场景
- Multi-Drivers(多驱动架构)
编码示例
1、简单工厂模式
简单工厂模式,只是做了一层简单的封装,将不同对象的实例化操作都单独放到了一个工厂类中。
当我们需要实例化某个对象时,只需把我们的需求告诉简单工厂类,然后由这个简单工厂类根据我们的需求去创建对应的对象即可。适用于简单的业务场景。
-
优点: 简单工厂模式可以根据需求,动态生成使用者所需类的对象,而使用者不用去知道怎么创建对象,使得各个模块各司其职,降低了系统的耦合性。
-
缺点: 扩展性差,违背了开闭原则(开闭原则指的是:软件实现应该对扩展开放,对修改关闭)。新增产品时,需要修改简单工厂类的代码。
实体角色:
- 产品的抽象类
- 具体的产品子类
- 简单工厂类
import abc
# 产品的抽象类
class Productor(metaclass=abc.ABCMeta):
@abc.abstractmethod
def product(self, car):
pass
# 更具体的某个产品类,是产品抽象类的子类
class Xiaomi(Productor):
"""
小米手机
"""
def product(self, price):
return f"制造一部小米手机,售价price元"
def __repr__(self):
return f"Xiaomi,id(self)"
# 更具体的某个产品类,是产品抽象类的子类
class Huawei(Productor):
"""
华为手机
"""
def product(self, price):
return f"制造一部华为手机,售价price元"
def __repr__(self):
return f"Huawei,id(self)"
# 简单工厂类
class PhoneBrandFactory:
"""
简单工厂
"""
def create_productor(self, brand):
if brand == "Xiaomi":
return Xiaomi()
if brand == "Huawei":
return Huawei()
else:
raise TypeError(f"没有名为brand的手机生产商。")
if __name__ == "__main__":
# 通过简单工厂类提供的接口函数来获得某个具体的产品类的对象
Xiaomi = PhoneBrandFactory().create_productor("Xiaomi")
Huawei = PhoneBrandFactory().create_productor("Huawei")
print(Xiaomi)
print(Huawei)
print(Xiaomi.product(2999))
print(Huawei.product(5999))
2、工厂方法模式
工厂方法模式,工厂类派生了任意个子工厂类,每个子工厂类对应一个具体的产品类,则某个产品类的对象的实例化就交由这个子工厂类来完成。
工厂方法模式是简单工厂模式的改进,当我们需要扩展一个新产品时,只需要扩展一个新的子工厂类即可,而不用去修改工厂类原有的代码,这样就符合了开闭原则。
-
优点: 扩展性好,符合了开闭原则。新增一种产品时,只需增加改对应的产品类和对应的工厂子类即可。同时,也使得每个产品类和对应的工厂子类符合了单一职责原则,每个工厂只负责一种产品,而不是由一个工厂去生成所有商品。
-
缺点: 当我们新增产品时,还需要提供对应的工厂类,系统中类的个数将会成倍增加,相当于增加了系统的复杂性。
实体角色:
- 产品的抽象类
- 具体的产品子类
- 工厂类
- 具体的工厂子类
import abc
# 产品的抽象类
class Productor(metaclass=abc.ABCMeta):
@abc.abstractmethod
def product(self, car):
pass
# 更具体的某个产品类,是产品抽象类的子类
class Xiaomi(Productor):
"""
小米手机
"""
def product(self, price):
return f"制造一部小米手机,售价price元"
def __repr__(self):
return f"Xiaomi,id(self)"
# 更具体的某个产品类,是产品抽象类的子类
class Huawei(Productor):
"""
华为手机
"""
def product(self, price):
return f"制造一部华为手机,售价price元"
def __repr__(self):
return f"Huawei,id(self)"
# 工厂类
class PhoneBrandFactory(metaclass=abc.ABCMeta):
"""
抽象工厂
"""
@abc.abstractmethod
def create_productor(self, brand):
pass
# 具体产品对应的子工厂类
class XiaomiFactory(PhoneBrandFactory):
def create_productor(self):
return Xiaomi()
# 具体产品对应的子工厂类
class HuaweiFactory(PhoneBrandFactory):
def create_productor(self):
return Huawei()
if __name__ == "__main__":
# 由这个子工厂类来完成对应的某个产品类的对象实例化
Xiaomi = XiaomiFactory().create_productor()
Huawei = HuaweiFactory().create_productor()
print(Xiaomi)
print(Huawei)
print(Xiaomi.product(2999))
print(Huawei.product(5999))
3、抽象工厂模式
抽象工厂模式,又是工厂方法模式的改进。工厂方法模式解决的是生产不同品牌的同一类型的电脑,而抽象工厂模式解决的是生产不同品牌的多种类型的电脑。
比如,工厂方法模式中的电脑工厂只能生产老式的台式电脑,而如果现在需要生产台式电脑,笔记本电脑,平板电脑等多个种类的电脑的话,那么工厂方法模式就不太方便了。而抽象工厂模式可以解决电脑工厂生产多个种类电脑的问题,也就是解决一个工厂生产多种类型的产品的问题。
如果我们需要台式电脑,又需要笔记本电脑,要多种产品时,工厂方法模式无法满足我们的需求;而抽象方法模式,提前在抽象工厂中,定义好了可能需要的多种产品,比如:台式电脑,笔记本电脑,平板电脑等,当有需求的时候,我们只需要创建相关子类和相关子工厂类即可。
-
优点: 抽象工厂类创建了多个类型的产品,当有需求时,可以创建相关子产品类和子工厂类来获取。也就是可以满足生产不同品牌的不同类型的电脑。
-
缺点: 扩展新种类产品时困难。抽象工厂模式需要我们在工厂抽象类中提前确定了可能需要的产品种类,以满足不同品牌的多种产品的需求。但是如果我们需要的产品种类并没有在工厂抽象类中提前确定,那我们就需要去修改工厂抽象类了,而一旦修改了工厂抽象类,那么所有的工厂子类也需要修改,这样显然扩展不方便。
实体角色:
- 产品功能特性抽象类
- 具体的产品功能特性子类
- 产品的抽象类
- 具体的产品子类
- 抽象工厂类
import abc
# 产品功能特性抽象类
class PhoneShell(metaclass=abc.ABCMeta):
@abc.abstractmethod
def shell(self):
pass
class Cpu(metaclass=abc.ABCMeta):
@abc.abstractmethod
def cpu(self):
pass
class OS(metaclass=abc.ABCMeta):
@abc.abstractmethod
def system(self):
pass
# 具体的产品功能特性类
class SmallShell(PhoneShell):
@property
def shell(self):
return "小屏幕"
class BigShell(PhoneShell):
@property
def shell(self):
return "大屏幕"
class SnapDragonCpu(Cpu):
@property
def cpu(self):
return "骁龙cpu"
class AppleCpu(Cpu):
@property
def cpu(self):
return "苹果cpu"
class android(OS):
@property
def system(self):
return "安卓系统"
class ios(OS):
@property
def system(self):
return "IOS系统"
# 产品的抽象类
class ProductPhone:
def __init__(self, factory):
self.factory = factory()
def product(self):
self.shell = self.factory.product_shell()
self.cpu = self.factory.product_cpu()
self.OS = self.factory.product_system()
def show_info(self):
print(f"self.factory", f"配置信息:self.shell.shell, self.cpu.cpu, self.OS.system")
# 具体的产品子类
class XiaomiFactory(PhoneFactory):
def product_shell(self):
return BigShell()
def product_cpu(self):
return SnapDragonCpu()
def product_system(self):
return Android()
def __repr__(self):
return "小米手机,售价2999!"
class IphoneFactory(PhoneFactory):
def product_shell(self):
return SmallShell()
def product_cpu(self):
return AppleCpu()
def product_system(self):
return IOS()
def __repr__(self):
return "苹果手机,售价8999!"
# 抽象工厂类
class PhoneFactory(metaclass=abc.ABCMeta):
@abc.abstractmethod
def product_shell(self):
pass
@abc.abstractmethod
def product_cpu(self):
pass
@abc.abstractmethod
def product_system(self):
pass
if __name__ == "__main__":
xiaomi = ProductPhone(XiaomiFactory)
xiaomi.product()
xiaomi.show_info()
iphone = ProductPhone(IphoneFactory)
iphone.product()
iphone.show_info()
以上是关于Python 设计模式 — 创建型模式 — 工厂模式的主要内容,如果未能解决你的问题,请参考以下文章
(转自精通Python设计模式)Python设计模式之创建型模式——1.工厂模式
[Python编程实战] 第一章 python的创建型设计模式1.1抽象工厂模式