[创建型]工厂方法模式

40 阅读4分钟

故事

时间来到了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)使用继承代替工厂方法不也挺好吗?

工厂方法的精髓在于,对一种产品的创建进行标准化。这样,客户代码就无需关系产品的创建细节,单纯使用继承无法规避这一点。而且不同风格产品的接口虽然一致,创建过程可能非常复杂,而且实现方式也有很大差异(比如陆运服务和空运服务),不适宜于挤在一个'工厂'中创建。