设计模式-抽象工厂模式

在设计模式中,抽象工厂模式 (Abstract Factory Pattern)是一个非常常见且重要的模式,它属于创建型模式,用于提供创建一组相关或相互依赖对象的接口,而无需指定具体类。它的核心思想是将"创建对象"这一功能封装到工厂类中,从而避免了直接实例化具体对象,进而实现了解耦。

抽象工厂模式适用于以下场景:

  • 需要生成多个相关对象,而这些对象往往具有相似的接口或行为。
  • 系统需要独立于其产品的创建、组合和表示。
  • 需要提供一个产品族,而每个产品族中的产品有类似的结构或行为。

在这篇文章中,我们将详细讲解抽象工厂模式的概念、结构、实现方式、优缺点以及使用场景,并通过一个实例帮助你更好地理解这一设计模式。

1. 抽象工厂模式的概念

抽象工厂模式定义了一个接口,用于创建相关的对象。它并不具体指明如何创建每一个对象,而是将具体的对象创建过程交给其子类来完成。通过这种方式,系统可以在不修改代码的情况下更容易地引入新的产品族。

1.1 主要角色

抽象工厂模式通常包括以下几个角色:

  • AbstractFactory(抽象工厂):定义创建一系列相关产品的接口。每个具体工厂类都实现这个接口。
  • ConcreteFactory(具体工厂):实现了创建具体产品对象的操作,负责创建产品族中的每个产品。
  • AbstractProduct(抽象产品):为每种产品定义一个接口,规定了产品的基本行为。
  • ConcreteProduct(具体产品):实现了抽象产品定义的接口,表示一类具体的产品。
  • Client(客户端):使用抽象工厂和抽象产品的接口,依赖于具体的工厂对象来创建产品。

通过这些角色,抽象工厂模式的目标是让客户端通过抽象工厂类来创建产品,而无需关心产品的具体实现。

2. 抽象工厂模式的结构

以下是一个典型的抽象工厂模式的结构图:图像来源

2.1 解释

  • AbstractFactory (抽象工厂)定义了创建 ProductAProductB 等产品的方法。
  • ConcreteFactory(具体工厂)实现了抽象工厂接口的具体方法,返回一个或多个具体的产品。
  • AbstractProduct(抽象产品)定义了产品的接口,所有具体产品都需要实现这些接口。
  • ConcreteProduct(具体产品)实现了抽象产品接口,代表了具体的产品。

3. 抽象工厂模式的实现

下面我们通过一个简单的例子来展示抽象工厂模式的实现过程。假设我们要开发一个界面库,支持多种操作系统(如 Windows 和 MacOS),每个操作系统下都有不同风格的按钮和输入框。

3.1 定义抽象产品

首先,定义一些抽象产品(如按钮和输入框)的接口。

python 复制代码
"""
两个抽象产品类,AbstractButton、AbstractTextField
"""
from abc import ABC, abstractmethod

# 抽象产品 - 按钮
class AbstractButton(ABC):
    @abstractmethod
    def click(self):
        pass

# 抽象产品 - 输入框
class AbstractTextField(ABC):
    @abstractmethod
    def render(self):
        pass

3.2 定义具体产品

接下来,我们为每个操作系统实现具体的产品类。

python 复制代码
"""
四个具体产品类
"""

# Windows平台的按钮和输入框
class WindowsButton(AbstractButton):
    def click(self):
        return "Windows Button Clicked!"

class WindowsTextField(AbstractTextField):
    def render(self):
        return "Windows TextField Rendered!"

# MacOS平台的按钮和输入框
class MacButton(AbstractButton):
    def click(self):
        return "Mac Button Clicked!"

class MacTextField(AbstractTextField):
    def render(self):
        return "Mac TextField Rendered!"

3.3 定义抽象工厂

然后,定义一个抽象工厂类,声明创建按钮和输入框的抽象方法。

python 复制代码
# 定义了一个抽象工厂类,并定义了两个抽象方法:create_button、create_text_field

class AbstractUIFactory(ABC):
    @abstractmethod 
    def create_button(self) -> AbstractButton: 
        pass 

    @abstractmethod 
    def create_text_field(self) -> AbstractTextField: 
        pass

3.4 定义具体工厂

实现具体的工厂类,用于创建具体的产品。

python 复制代码
"""
定义了两个具体工厂,分别是WindowsFactory、MacFactory
这两个工厂分别实现了windows下和mac下的create_button、create_text_field
"""

# Windows工厂
class WindowsFactory(AbstractUIFactory):
    def create_button(self) -> AbstractButton:
        return WindowsButton()

    def create_text_field(self) -> AbstractTextField:
        return WindowsTextField()

# Mac工厂
class MacFactory(AbstractUIFactory):
    def create_button(self) -> AbstractButton:
        return MacButton()

    def create_text_field(self) -> AbstractTextField:
        return MacTextField()

3.5 客户端代码

最后,在客户端代码中,我们使用工厂来获取特定平台的产品。

python 复制代码
"""
定义了一个客户端,客户端接收一个具体工厂实例,然后分别调用工厂里的create_button、create_text_field
由于工厂不同,从而生产出了不的产品
"""

def client_code(factory: AbstractUIFactory):
    button = factory.create_button()
    text_field = factory.create_text_field()

    print(button.click())
    print(text_field.render())

# 使用 Windows 工厂
print("Windows Factory:")
windows_factory = WindowsFactory()
client_code(windows_factory)

# 使用 Mac 工厂
print("\nMac Factory:")
mac_factory = MacFactory()
client_code(mac_factory)

3.6 运行结果

Windows Factory:
Windows Button Clicked!
Windows TextField Rendered!

Mac Factory:
Mac Button Clicked!
Mac TextField Rendered!

4. 抽象工厂模式的优缺点

4.1 优点

  1. 产品一致性保证:抽象工厂模式确保每个产品族中的产品能够一致地搭配使用,避免了不兼容的产品组合。
  2. 可扩展性强:如果需要支持新的产品族,只需添加新的具体工厂和具体产品,而不需要修改现有的代码,这符合"对扩展开放,对修改关闭"的设计原则。
  3. 解耦:客户端代码不依赖于具体的产品类,只依赖于抽象工厂和抽象产品,减少了类之间的耦合。

4.2 缺点

  1. 增加了系统的复杂性:每新增一个产品族,就需要创建新的工厂类和产品类,系统的类数目会迅速增加,导致代码维护变得复杂。
  2. 难以支持不同种类的产品族:如果系统中需要支持大量不同种类的产品族,可能会导致工厂类变得非常庞大,难以维护。

5. 适用场景

  • 需要生成多个相关或相互依赖的产品对象,而这些对象的接口可能会有差异。
  • 系统要独立于产品的创建、组合和表示,并且产品的具体实现可能会随时发生变化。
  • 需要确保产品的一致性,并且产品的不同实现或种类在某些场合下不能互换使用。

6. 抽象工厂模式与工厂方法模式的区别

抽象工厂模式(Abstract Factory Pattern)和工厂方法模式(Factory Method Pattern)都是属于创建型设计模式,它们的目标是通过引入工厂类来封装对象的创建过程,从而达到解耦的目的。不过,它们之间有一些关键的区别。

特性 工厂方法模式 (Factory Method Pattern) 抽象工厂模式 (Abstract Factory Pattern)
定义 定义一个创建对象的接口,让子类决定实例化哪一个类。 提供一个创建一系列相关或相互依赖对象的接口,而无需指定具体类。
类的结构 只有一个工厂方法,通常有一个抽象工厂类和多个具体工厂类,每个工厂类负责创建一个具体产品。 包含多个工厂方法,用于创建多个相关的产品,每个产品有对应的工厂类。
产品的数量 只创建一种产品。 创建一系列相关或相互依赖的产品。
产品的依赖关系 各个产品之间没有直接的依赖关系。 各个产品之间存在依赖关系,通常需要一个产品族。
客户端角色 客户端通过调用具体工厂的工厂方法来创建一个产品。 客户端通过抽象工厂来获取多个相关的产品,而无需知道这些产品的具体实现类。
扩展性 通过新增具体工厂和具体产品来扩展,但扩展较为简单。 通过新增具体工厂和产品族来扩展,通常扩展相对复杂,需要增加新的产品族和多个具体产品类。
适用场景 用于需要创建单个产品的场景,且产品的变化较少。 用于需要创建多个相关产品的场景,尤其是当产品之间存在依赖关系时,确保产品的一致性和兼容性。
实例 例如,汽车工厂可以生产一辆车(一个产品),不同工厂生产不同品牌的车(不同具体产品)。 例如,用户界面框架,Windows 和 MacOS 上的按钮、输入框等一组产品需要被创建(一个产品族)。
实现复杂度 相对较简单,主要通过工厂方法来实现对象的创建。 相对较复杂,需要设计多个工厂方法和产品类,且每个工厂方法可能创建多个相关产品。
  • 工厂方法模式注重于创建单一产品的实例,主要通过定义一个工厂方法来实现。
  • 抽象工厂模式则是用来创建多个相关或相互依赖的产品,它不仅仅是创建一个产品,而是创建一整套产品族。
  • 工厂方法模式:当系统只需要创建一个产品时,或者有多个具体工厂,但每个工厂只负责一个产品的创建。
  • 抽象工厂模式:当系统需要创建一系列相关的产品时,例如涉及到多个产品族时,可以通过抽象工厂来进行管理。
相关推荐
Java知识日历2 小时前
【内含例子代码】Spring框架的设计模式应用(第二集)
java·开发语言·后端·spring·设计模式
暗碳6 小时前
cloudns二级免费域名python更新ipv6 dns记录
开发语言·python
BlackPercy6 小时前
[paddle] 非线性拟合问题的训练
python·机器学习·paddlepaddle·paddle
wcyd8 小时前
如何使用Python生成词云图:结合`wordcloud`、`imageio`、`collections`和`jieba`分词模块
开发语言·python·信息可视化
ONE_PUNCH_Ge8 小时前
Python3 正则表达式
python
cxr8289 小时前
基于微信小程序的面部动作检测系统
人工智能·python·算法·计算机视觉·微信小程序·小程序·视觉检测
橙子 chen9 小时前
工具函数 - 调用http
java·大数据·网络·数据库·python·网络协议·http
羊小猪~~9 小时前
基于RNN模型的心脏病预测,提供tensorflow和pytorch实现
pytorch·python·rnn·深度学习·神经网络·机器学习·tensorflow
多恩Stone9 小时前
【Triton-ONNX】如何使用 ONNX 模型服务与 Triton 通信执行推理任务上-Triton快速开始
服务器·开发语言·python·docker
聪明的骑士10 小时前
Python基础语法(上)
开发语言·python·pycharm