前言
在上一篇博文中,我们讲述了模板方法模式:在父类中定义统一的接口,处理流程,在子类中实现具体的业务逻辑。如果我们用模板方法来生成某个类的实例。就是今天要讲的工厂方法模式。
工厂方法模式一般会有抽象产品、抽象工厂、具体产品、具体工厂这四种角色。不同的实现会有略微的差异,具体应用仁者见仁!
在工厂方法模式中,父类决定实例的生成方式,但并不决定所要生成的具体的类。生成什么样的实例完全交给子类去负责。这样就可以将生成实例的框架和实际负责生成实例的类解耦。
示例
说明
这段实例功能是制作ID card的类实例,通过一个工厂,指定名称之后,就可以创建出不同的idcard实例。
类表
library | class name | description |
---|---|---|
framework | Product | 定义了抽象方法use |
framework | Factory | 实现了create方法的类 |
idcard | IDCard | 实现了use方法的子类 |
idcard | IDCardFactory | 实现了createProduct registerProduct方法的子类 |
类图
代码实现
代码结构
Product类
"""
@Time: 2023/4/9 16:07
@Auth: CivilDog
@File: Product.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
import abc
class SubClassNotImplementException(Exception):
def __str__(self):
return "This method should be implemented in subclass!"
class Product(metaclass=abc.ABCMeta):
"""
产品的抽象类
"""
def __init__(self):
pass
@abc.abstractmethod
def use(self):
pass
def get_name(self):
raise SubClassNotImplementException
Factory类
"""
@Time: 2023/4/9 16:08
@Auth: CivilDog
@File: Factory.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
import abc
class Factory(metaclass=abc.ABCMeta):
"""
创建产品的工厂的抽象类
"""
def __init__(self):
pass
def create(self, owner: str):
p = self.create_product(owner)
self.register_product(p)
return p
@abc.abstractmethod
def create_product(self, owner: str):
pass
@abc.abstractmethod
def register_product(self, product):
pass
IDCard类
"""
"""
@Time: 2023/4/9 16:12
@Auth: CivilDog
@File: IDCard.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
from DesignMode.FactoryMethodMode.FrameWork.Product import Product
class IDCard(Product):
"""
具体产品类
"""
def __init__(self, owner: str):
super(IDCard, self).__init__()
print(f"make {owner}'s Id card.")
self.owner = owner
def use(self):
print(f"using {self.owner}'s Id card!")
def get_name(self):
return self.owner
IDCardFactory类
"""
@Time: 2023/4/9 16:15
@Auth: CivilDog
@File: IDCardFactory.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
from DesignMode.FactoryMethodMode.FrameWork.Factory import Factory
from DesignMode.FactoryMethodMode.FrameWork.Product import Product
from DesignMode.FactoryMethodMode.IDCard.IDCard import IDCard
class IDCardFactory(Factory):
"""
具体产品的具体创建工厂类
"""
def __init__(self):
super(IDCardFactory, self).__init__()
self.owners = []
def create_product(self, owner: str):
return IDCard(owner)
def register_product(self, product: Product):
self.owners.append(product.get_name())
def get_owners(self):
return self.owners
Client类
"""
@Time: 2023/4/9 16:26
@Auth: CivilDog
@File: Client.py
@IDE: PyCharm
@Motto: Nothing is impossible
"""
from DesignMode.FactoryMethodMode.IDCard.IDCardFactory import IDCardFactory
class Client:
@staticmethod
def run(*args, **kwargs):
factory = IDCardFactory()
card1 = factory.create("Tom")
card2 = factory.create("Jerry")
card3 = factory.create("Jessi")
card1.use()
card2.use()
card3.use()
if __name__ == '__main__':
Client.run()
输出内容
make Tom's Id card.
make Jerry's Id card.
make Jessi's Id card.
using Tom's Id card!
using Jerry's Id card!
using Jessi's Id card!
Process finished with exit code 0
小结
从上面的代码可以看出来,我们要实现具体业务同框架的分离,那么每一个产品都需要实现继承factory和product,实现自定义的concretefactory和concretrproduct子类。这样就会显得臃肿。有些工厂方法应用中,会将所有product的生成放在一个工厂当中,这样可以避免了许多不同factory的产生,但是代码结构相对出现了浑浊,每一种实现都有其优缺点,具体情况具体抉择。
总结
工厂方法模式比较简单,虽然可以令代码更加清晰,但是当业务复杂的时候,会造成代码过度臃肿。
通过工厂方法模式来创建实例,而非直接实例化,可以防止父类同其他类过度耦合。