设计模式-工厂模式

概念:

工厂模式属于创建型设计模式,核心思想是将对象的创建过程封装到工厂类中,客户端无需关心具体对象的创建细节,实现创建与使用的解耦。

模式分类

  1. 简单工厂模式(静态工厂)

  2. 工厂方法模式(多态工厂)

  3. 抽象工厂模式(产品族工厂)

工厂模式的核心优势

1. 解耦创建与使用

  • 客户端代码无需依赖具体类,只需要与抽象接口交互
  • 符合依赖倒置原则(DIP)

2. 可扩展性强

  • 新增产品时,只需添加新的具体工厂和产品类
  • 符合开闭原则(对扩展开放,对修改关闭)

3. 统一创建逻辑

  • 将复杂的对象初始化过程封装在工厂中
  • 避免代码重复(例如:参数验证、资源分配)

简单工厂模式,抽象公共接口,然后封装不同类型,最后创建一个工厂(类比名)统一处理这些封装对象,然后在实现的时候根据传递的参数实例化不同的对象。

python 复制代码
# 步骤1:定义产品接口
class Car:
    def drive(self):
        pass

# 步骤2:创建具体产品
class Tesla(Car):
    def drive(self):
        print("特斯拉电动车启动...")

class BMW(Car):
    def drive(self):
        print("宝马燃油车启动...")

# 步骤3:创建工厂
class CarFactory:
    @staticmethod
    def create_car(brand):
        if brand == "tesla":
            return Tesla()
        elif brand == "bmw":
            return BMW()
        else:
            raise ValueError("不支持的车型")

# 使用示例
if __name__ == "__main__":
    # 通过工厂创建对象
    car1 = CarFactory.create_car("tesla")
    car2 = CarFactory.create_car("bmw")

    car1.drive()  # 输出:特斯拉电动车启动...
    car2.drive()  # 输出:宝马燃油车启动...

代码结构解析:

  1. Car 是产品基类(接口)
  2. TeslaBMW 是具体产品
  3. CarFactory 是工厂类,根据参数创建不同产品
  4. 使用者只需要和工厂交互,不需要知道具体类的创建细节

工厂模式的核心优势:将对象的创建和使用解耦,当需要新增产品时,只需要扩展工厂类,不需要修改已有代码。


下面以工厂方法模式为例进行完整实现,把产品和工厂都进行抽象,在最后调用的时候不需要实例化最上层的接口:


Python 代码实现

1. 定义抽象产品接口

python 复制代码
from abc import ABC, abstractmethod

# 抽象产品:车辆接口
class Vehicle(ABC):
    @abstractmethod
    def start_engine(self):
        pass

    @abstractmethod
    def stop_engine(self):
        pass

2. 实现具体产品类

python 复制代码
# 具体产品:电动车
class ElectricCar(Vehicle):
    def start_engine(self):
        print("⚡️ 电动车电机启动(无声)")

    def stop_engine(self):
        print("⚡️ 电动车电机关闭")

# 具体产品:燃油车
class GasolineCar(Vehicle):
    def start_engine(self):
        print("🔥 燃油车发动机启动(轰鸣声)")

    def stop_engine(self):
        print("🔥 燃油车发动机关闭")

3. 定义抽象工厂接口

python 复制代码
# 抽象工厂
class VehicleFactory(ABC):
    @abstractmethod
    def create_vehicle(self) -> Vehicle:
        pass

4. 实现具体工厂类

python 复制代码
# 具体工厂:电动车工厂
class ElectricCarFactory(VehicleFactory):
    def create_vehicle(self) -> Vehicle:
        print("制造电动车:安装电池组、电机...")
        return ElectricCar()

# 具体工厂:燃油车工厂
class GasolineCarFactory(VehicleFactory):
    def create_vehicle(self) -> Vehicle:
        print("制造燃油车:安装发动机、油箱...")
        return GasolineCar()

5. 客户端使用示例

python 复制代码
def client_code(factory: VehicleFactory):
    # 客户端无需知道具体产品类型
    vehicle = factory.create_vehicle()
    vehicle.start_engine()
    vehicle.stop_engine()
    print("-" * 40)

if __name__ == "__main__":
    # 选择电动车工厂
    electric_factory = ElectricCarFactory()
    client_code(electric_factory)

    # 选择燃油车工厂
    gasoline_factory = GasolineCarFactory()
    client_code(gasoline_factory)

输出结果

python 复制代码
制造电动车:安装电池组、电机...
⚡️ 电动车电机启动(无声)
⚡️ 电动车电机关闭
----------------------------------------
制造燃油车:安装发动机、油箱...
🔥 燃油车发动机启动(轰鸣声)
🔥 燃油车发动机关闭
----------------------------------------

适用场景

  1. 需要创建多种类型对象,且这些对象有共同接口
  2. 创建过程涉及复杂初始化逻辑
  3. 需要根据运行时条件动态选择创建哪种对象
  4. 希望隐藏具体类的实现细节(例如SDK开发)

工厂方法 vs 简单工厂

特性 工厂方法 简单工厂
扩展性 新增产品只需加新工厂类 需要修改工厂类代码
符合开闭原则
复杂度 较高(需要维护更多类) 较低
适用场景 大型项目、产品类型多 小型项目、产品类型少

场景1:需要创建多种类型对象,且这些对象有共同接口

实际案例:跨平台文件存储服务

假设你需要支持将文件存储到不同云服务(阿里云OSS、腾讯云COS、AWS S3),但它们的上传/下载接口不同。

python 复制代码
from abc import ABC, abstractmethod

# 公共接口
class CloudStorage(ABC):
    @abstractmethod
    def upload_file(self, local_path: str, remote_path: str):
        pass

    @abstractmethod
    def download_file(self, remote_path: str, local_path: str):
        pass

# 具体产品:阿里云OSS
class AliyunOSS(CloudStorage):
    def upload_file(self, local_path: str, remote_path: str):
        print(f"[阿里云] 上传 {local_path} 到 {remote_path}")

    def download_file(self, remote_path: str, local_path: str):
        print(f"[阿里云] 下载 {remote_path} 到 {local_path}")

# 具体产品:腾讯云COS
class TencentCOS(CloudStorage):
    def upload_file(self, local_path: str, remote_path: str):
        print(f"[腾讯云] 上传 {local_path} 到 {remote_path}")

    def download_file(self, remote_path: str, local_path: str):
        print(f"[腾讯云] 下载 {remote_path} 到 {local_path}")

# 工厂根据配置选择实现
class CloudStorageFactory:
    @staticmethod
    def create_storage(provider: str) -> CloudStorage:
        if provider == "aliyun":
            return AliyunOSS()
        elif provider == "tencent":
            return TencentCOS()
        else:
            raise ValueError("不支持的云服务商")

# 客户端代码无需知道具体实现
storage = CloudStorageFactory.create_storage("aliyun")
storage.upload_file("data.txt", "backup/data.txt")

场景2:创建过程涉及复杂初始化逻辑

实际案例:构建数据库连接对象

数据库连接需要处理参数校验、连接池初始化、超时设置等复杂步骤。

python 复制代码
class DatabaseConnection:
    def __init__(self, host: str, port: int, user: str, password: str):
        # 复杂的初始化过程
        self._validate_config(host, port)
        self._init_connection_pool()
        self._set_timeout(30)
        print(f"已连接到 {host}:{port}")

    def _validate_config(self, host, port):
        if not host:
            raise ValueError("Invalid host")
        # 更多校验逻辑...

    def _init_connection_pool(self):
        print("初始化连接池...")

    def _set_timeout(self, seconds):
        print(f"设置超时时间:{seconds}秒")

class DatabaseFactory:
    @staticmethod
    def create_connection(config: dict) -> DatabaseConnection:
        # 封装所有复杂逻辑
        return DatabaseConnection(
            host=config["host"],
            port=config["port"],
            user=config["user"],
            password=config["password"]
        )

# 使用示例
config = {
    "host": "127.0.0.1",
    "port": 3306,
    "user": "admin",
    "password": "secret"
}
db = DatabaseFactory.create_connection(config)

场景3:运行时动态选择创建哪种对象

实际案例:根据操作系统创建不同风格的UI组件

在跨平台应用中,需要根据当前操作系统动态创建对应风格的按钮。

python 复制代码
import platform

# 抽象产品:按钮
class Button(ABC):
    @abstractmethod
    def render(self):
        pass

# 具体产品:Windows风格按钮
class WindowsButton(Button):
    def render(self):
        print("渲染一个Windows风格的按钮")

# 具体产品:Mac风格按钮
class MacButton(Button):
    def render(self):
        print("渲染一个Mac风格的按钮")

class UIFactory:
    @staticmethod
    def create_button() -> Button:
        # 根据运行时系统类型决定
        os_name = platform.system()
        if os_name == "Windows":
            return WindowsButton()
        elif os_name == "Darwin":  # macOS
            return MacButton()
        else:
            raise NotImplementedError("不支持的操作系统")

# 客户端代码
button = UIFactory.create_button()
button.render()  # 输出取决于当前操作系统

场景4:隐藏具体实现细节(SDK开发)

实际案例:支付SDK封装

作为SDK提供方,你希望隐藏支付宝/微信支付的具体实现,只暴露统一接口。

python 复制代码
# SDK对外暴露的接口
class PaymentProcessor(ABC):
    @abstractmethod
    def pay(self, amount: float):
        pass

# 具体实现1(SDK内部实现)
class AlipayProcessor(PaymentProcessor):
    def pay(self, amount: float):
        print(f"调用支付宝接口支付 {amount} 元")

# 具体实现2(SDK内部实现)
class WechatPayProcessor(PaymentProcessor):
    def pay(self, amount: float):
        print(f"调用微信支付接口支付 {amount} 元")

class PaymentFactory:
    @staticmethod
    def create_processor(payment_type: str) -> PaymentProcessor:
        if payment_type == "alipay":
            return AlipayProcessor()
        elif payment_type == "wechat":
            return WechatPayProcessor()
        else:
            raise ValueError("不支持的支付方式")

# 开发者使用SDK时
processor = PaymentFactory.create_processor("alipay")
processor.pay(100.0)  # 开发者无需知道支付宝的具体实现

总结:工厂模式的核心价值

场景 解决的问题 实际效果
多种类型对象 + 共同接口 统一不同实现的访问方式 客户端代码无需关心具体类型
复杂初始化逻辑 封装创建细节避免代码重复 简化调用方代码,集中管理创建逻辑
运行时动态选择 避免在业务代码中写大量if-else 提升代码可维护性
隐藏实现细节(如SDK) 降低使用方与实现的耦合度 方便后续替换实现而不影响调用方

通过工厂模式,你可以将 变化的创建逻辑稳定的业务逻辑 分离,这正是面向对象设计原则中「封装变化」的经典体现。

相关推荐
weixin_4723394611 分钟前
PyCharm 安装教程
ide·python·pycharm
星川皆无恙1 小时前
大数据产品销售数据分析:基于Python机器学习产品销售数据爬虫可视化分析预测系统设计与实现
大数据·运维·爬虫·python·机器学习·数据分析·系统架构
shenyan~1 小时前
关于Python:9. 深入理解Python运行机制
开发语言·python
白熊1881 小时前
【计算机视觉】pyrealsense2:Intel RealSense 深度相机的 Python 接口实战指南
python·数码相机·计算机视觉
还是大剑师兰特2 小时前
vue源代码采用的设计模式分解
javascript·vue.js·设计模式
殇淋狱陌2 小时前
【Python】常用命令提示符
开发语言·python·虚拟环境
高效匠人3 小时前
文章五《卷积神经网络(CNN)与图像处理》
图像处理·人工智能·python·cnn
zhanzhan01093 小时前
ubantu安装CUDA
人工智能·python·深度学习
Draina3 小时前
爬虫技术-利用Python和Selenium批量下载动态渲染网页中的标准文本文件
爬虫·python·selenium·网络爬虫
io_T_T4 小时前
(NLP)关键词提取之——TF-IDF解析
python·nlp