故事
时间来到了2010年,王四的作坊生意很好,但有了一些新烦恼。
1)生意好的一个人实在忙不过来,老婆也来帮忙了,还是人手不够。
2)附近各村的人经济水平都提升了,对桌椅的要求也提高了,一种风格满足不了他们的要求。
怎么办?招一些木匠来做,还要多搞一些风格来迎合买家口味。
招人做,要考虑:
1)怎么保证质量?
2)怎么提高效率?
根据王四的调查,大家喜欢的桌椅风格有:中式风格和现代风格。王思也考虑,以后可能要搞其他更多风格,因为用户的口味在变。
生产这两种风格的桌椅,对空间、设备、工序、木匠技能的要求等等不太一样,都在一个工作区间制作的话,相互影响反而不方便,更何况以后还要搞其他风格?
他决定先搞两个车间来分别制作中式风格桌椅和现代风格桌椅,并且两个车间都遵循王四制定的生产规范。
王四把自己的作坊搞成了标准化的车间,而且还一下搞了两个车间。现在车间的生产效率更高了,老王挣了更多的钱,高兴的合不拢嘴。大家也都觉得王四厉害,算的上一个本土企业家了。
问题
故事 | 抽象 |
---|---|
需要制作两种风格的桌椅,将来甚至可能要支持更多的风格。 如果就放在一个车间来制作,相互影响,以后也不好支持更多风格。 | 产品的创建,没有考虑到子类,已与具体的类深度绑定。 现在需要支持更多子类的创建,需要改动创建产品的许多代码。 |
解决方法
故事 | 抽象 |
---|---|
定义一个统一的生产标准,在不同的车间生产不同风格的产品。 | 工厂接口定义一个工厂方法,创建产品的功能延迟到工厂的子类实现。 |
要点
1)核心在于方法,而不是工厂。
2)这个方法被叫做”工厂方法“,工厂方法是工厂的一个抽象方法。
3)工厂方法对创建产品的过程进行抽象。
4)工厂方法考虑的如何标准化地创建一种产品。
5)工厂方法的精髓在于,对一种产品的创建进行标准化。
6)工厂方法的”工厂“其实更像一个车间。
模式适用场景
- 将来要增加一种风格的产品,你可以增加一个创建者子类,然后重写其工厂方法。
代码实现
from __future__ import annotations
from abc import ABC, abstractmethod
class TableSuite(ABC):
"""
抽象产品类
"""
@abstractmethod
def perform_function(self) -> str:
pass
class TableSuiteCreator(ABC):
"""
TableSuiteCreator声明创建桌椅套装的工厂方法:create_table_suite()。
TableSuiteCreator的子类实现该工厂方法。
"""
@abstractmethod
def create_table_suite(self) -> TableSuite:
"""
TableSuiteCreator其实也可以提供工厂方法的默认实现。
"""
pass
class ChineseTableSuiteCreator(TableSuiteCreator):
"""
工厂方法返回的是抽象的产品类型,这样使得创建者与具体的产品子类无关。
"""
def create_table_suite(self) -> TableSuite:
return ChineseTableSuite()
class ModernTableSuiteCreator(TableSuiteCreator):
def create_table_suite(self) -> TableSuite:
return ModernTableSuite()
"""
具体产品类实现抽象产品类的方法。
"""
class ChineseTableSuite(TableSuite):
"""
中式风格桌椅套装
"""
def perform_function(self):
"""发挥作用"""
print("{中式风格桌椅发挥作用,让人觉得古典优雅}")
class ModernTableSuite(TableSuite):
"""
现代风格桌椅套装
"""
def perform_function(self):
"""发挥作用"""
print("{现代风格桌椅发挥作用,让人觉得简洁实用}")
def client_code(creator: TableSuiteCreator) -> None:
"""
客户代码接受一个(桌椅)创建者对象作为参数,该对象的类型可以是抽象类的任一子类。
"""
print(f"客户代码: 我不知道创建者是哪个子类 ,我知道调用create_table_suite()就行。")
table_suite = creator.create_table_suite()
table_suite.perform_function()
if __name__ == "__main__":
client_code(ChineseTableSuiteCreator())
print("\n")
client_code(ModernTableSuiteCreator())
运行输出:
客户代码: 我不知道创建者是哪个子类 ,我知道调用create_table_suite()就行。
{中式风格桌椅发挥作用,让人觉得古典优雅}
客户代码: 我不知道创建者是哪个子类 ,我知道调用create_table_suite()就行。
{现代风格桌椅发挥作用,让人觉得简洁实用}
思考
1)如果在一个典型工厂方法的”工厂“中增加新的供的工厂方法,会怎样?
——工厂方法就更加像(没有说就是)抽象工厂了。
2)使用继承代替工厂方法不也挺好吗?
工厂方法的精髓在于,对一种产品的创建进行标准化。这样,客户代码就无需关系产品的创建细节,单纯使用继承无法规避这一点。而且不同风格产品的接口虽然一致,创建过程可能非常复杂,而且实现方式也有很大差异(比如陆运服务和空运服务),不适宜于挤在一个'工厂'中创建。