Python 设计模式之抽象工厂模式

文章目录

抽象工厂模式属于创建型设计模式,一般用来创建复杂的对象,这种对象由许多小对象组成,这些小对象都属于某个特定的类别。


从一个例子谈起

常见的例子是在家具商城中,有家具产品:椅子和沙发等等;这些产品同时有中式、日式等风格。如果用户期望一批日式风格的家具,你就得给它一批日式风格的家具。这里中式风格的家具生产厂就是一个复杂对象,而具体的中式椅子就是小对象。

假设现在客户端代码希望通过调用代码,生产出一批家具,这批家具必须风格一致。没有使用这种设计模式前,我们可能会这样实现代码。

python 复制代码
class ChinaSofa:
    @classmethod
    def create_sofa(cls):
        return ChinaSofa()

    def __str__(self):
        return "china style sofa"

class ChinaChair:
    @classmethod
    def create_chair(cls):
        return ChinaChair()

    def __str__(self):
        return "china style chair"

class JapanSofa:
    @classmethod
    def create_sofa(cls):
        return JapanSofa()

    def __str__(self):
        return "japan style sofa"

class JapanChair:
    @classmethod
    def create_chair(cls):
        return JapanChair()

    def __str__(self):
        return "japan style chair"


def main():
     print(ChinaSofa.create_sofa())
     print(ChinaChair.create_chair())

main()

这里 main 函数可以理解为客户端代码,我们看到在生产某种风格的产品时,代码需要知道用 ChinaSofa 类和 ChinaChair

python 复制代码
print(ChinaSofa.create_sofa())
print(ChinaChair.create_chair())

这里有两个明显的缺点:

  1. 如果在产品非常多的情况下,使用者可能会在代码中混入其他风格的类来生成产品。这意味着需要使用者很大的心智负担
  2. 如果现在增加一种欧式风格的沙发和椅子,我们就需要修改 main 函数的代码,即代码间存在耦合

作为客户端代码的开发者会更希望自己不需要关注生产中式风格的椅子用哪个类、日式风格的椅子又是哪个类。对他来说理想的行为应该是:
client factory 未来都制作中式风格的家具给我 我要把椅子 制作中式风格的椅子 我要张沙发 制作中式风格的沙发 client factory

基于这样的设想,可以预见我们的main 函数将是这样的:

python 复制代码
def main():
	# 风格的选择可以作为配置文件或者函数参数传入
    factory=ChinaStyle() 
    print(factory.create_sofa())
    print(factory.create_chair())

在这种调用形式下,我们解决了上面提到的两个缺点,那么该如何实现呢?

抽象工厂模式的组件构成

在进入实现之前,需要了解下抽象工厂模式由哪些组件组成:

  1. 抽象工厂

    抽象工厂是一个高层次的蓝图,它定义了创建相关对象族的一系列规则,而无需指定具体的类。它声明了一系列方法,每个方法负责创建一种特定类型的对象,并确保具体工厂遵循一个通用接口,从而提供一种一致的方式来生成相关的对象集。

  2. 具体的工厂

    具体工厂实现抽象工厂定义的接口函数。它包含在一个系列中创建特定对象实例的逻辑。一般会存在多个具体工厂,每个工厂都是为生产一个不同的相关对象系列而量身定制的。

  3. 抽象的产品

    抽象产品通过定义一组通用方法或属性来表示相关对象的系列。它是一个系列中所有具体产品都必须遵守的抽象或接口类型,并为具体产品的互换使用提供了统一的方式。

  4. 具体的产品

    它们是由具体工厂创建的对象的实际实例。它们实现抽象产品中声明的方法,确保族内的一致性,并属于相关对象的特定类别或族。

  5. 客户端

    客户利用抽象工厂创建对象系列,无需指定具体类型,并通过抽象产品提供的抽象接口与对象交互。客户可通过更改具体工厂实例,灵活地在对象系列之间无缝切换。

具体的调用逻辑
抽象产品 具体产品1 class 具体产品2 class 客户端 抽象工厂 具体工厂1 具体工厂2

实际上我们可以忽略实现抽象产品

根据抽象工厂模式实现

根据上面的组件介绍,我们可以对前文的例子进行对号入座:

  1. 客户端根据期望,用特定的工厂类生成工厂实例。这些工厂类继承自一个抽象的工厂类;
  2. 抽象工厂类定义了一系列可以生成产品实例的抽象函数,因此特定的工厂类通过重写这些函数,使得他们可以生成自己系列的产品对象

根据期望的行为给出接口的关系图:

接下来就是照着这张图实现:

python 复制代码
from abc import ABC, abstractmethod

class FurnitureFactory(ABC):
    @abstractmethod
    def create_sofa(self):
        pass

    @abstractmethod
    def create_chair(self):
        pass

class ChinaStyle(FurnitureFactory):
    def create_sofa(self):
        return ChinaStyleSofa()

    def create_chair(self):
        return ChinaStyleChair()


class JapanStyle(FurnitureFactory):
    def create_sofa(self):
        return JapanStyleSofa()

    def create_chair(self):
        return JapanStyleChair()

class Sofa(ABC):
    def can_sleep():
        return "the man can sleep on it"

class ChinaStyleSofa(Sofa):
    def __str__(self):
        return "china style sofa"

class JapanStyleSofa():
    def __str__(self):
        return "japan style sofa"

class Chair(ABC):
    def can_sit():
        return "the man can sit down"

class ChinaStyleChair(Chair):
    def __str__(self):
        return "china style chair"

class JapanStyleChair(Chair):
    def __str__(self):
        return "japan style chair"

def main():
    factory = ChinaStyle()
    print(factory.create_sofa())
    print(factory.create_chair())

main()

抽象工厂模式的缺点

  • 对比这两段代码,可以发现这种设计模式下的代码更加复杂,它实现了很多的抽象工厂和抽象产品接口,而在这个简单的例子中显得有些多余。因此对于简单的系统而言,这种模式有时并不适合,它带来的代码复杂度大过了它带来的优点。
相关推荐
测试老哥几秒前
外包干了两年,技术退步明显。。。。
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展
終不似少年遊*3 分钟前
美国加州房价数据分析01
人工智能·python·机器学习·数据挖掘·数据分析·回归算法
如若12331 分钟前
对文件内的文件名生成目录,方便查阅
java·前端·python
西猫雷婶1 小时前
python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶
开发语言·python·opencv
老刘莱国瑞2 小时前
STM32 与 AS608 指纹模块的调试与应用
python·物联网·阿里云
一只敲代码的猪2 小时前
Llama 3 模型系列解析(一)
大数据·python·llama
Hello_WOAIAI3 小时前
批量将 Word 文件转换为 HTML:Python 实现指南
python·html·word
winfredzhang3 小时前
使用Python开发PPT图片提取与九宫格合并工具
python·powerpoint·提取·九宫格·照片
矩阵推荐官hy147623 小时前
短视频矩阵系统种类繁多,应该如何对比选择?
人工智能·python·矩阵·流量运营
测试19983 小时前
外包干了2年,技术退步明显....
自动化测试·软件测试·python·功能测试·测试工具·面试·职场和发展