设计模式-工厂模式

概念:

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

模式分类

  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) 降低使用方与实现的耦合度 方便后续替换实现而不影响调用方

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

相关推荐
内存不泄露5 分钟前
基于 Spring Boot 的医院预约挂号系统(全端协同)设计与实现
java·vue.js·spring boot·python·flask
码农幻想梦9 分钟前
实验7 知识表示与推理
开发语言·人工智能·python
写代码的【黑咖啡】12 分钟前
深入理解 Python 中的 SQLAlchemy
开发语言·python·oracle
未定义.22121 分钟前
第1篇:0基础入门!Python+Selenium环境搭建与第一个自动化脚本
python·功能测试·selenium·自动化·jenkins·pytest
特行独立的猫22 分钟前
python+Proxifier+mitmproxy实现监听本地网路所有的http请求
开发语言·爬虫·python·http
深蓝电商API22 分钟前
Scrapy Spider 参数化:动态传入 start_urls 和自定义设置
爬虫·python·scrapy
CCPC不拿奖不改名24 分钟前
基于FastAPI的API开发(爬虫的工作原理):从设计到部署详解+面试习题
爬虫·python·网络协议·tcp/ip·http·postman·fastapi
___波子 Pro Max.35 分钟前
Python中Optional类型的作用解析
python
没学上了37 分钟前
Pycharm修改环境
ide·python·pycharm
就这个丶调调39 分钟前
Python中使用OpenAI实现AI问答:流式返回、记忆存储与工具调用详解
python·openai·流式响应·工具调用·ai问答·记忆存储