本文以python为例,简单介绍工厂函数。
工厂函数
工厂函数(Factory Function)是一种常见的设计模式,尤其适用于面向对象编程和函数式编程场景中,用来 动态创建对象 或 封装复杂初始化逻辑。
Definition
工厂函数本质上是一个返回对象的函数,而不是类的构造函数(init)。它根据传入的参数决定返回什么类型或配置的对象。
1 2 3 4 5 6 7
| def animal_factory(animal_type): if animal_type == "dog": return Dog() elif animal_type == "cat": return Cat() else: raise ValueError("Unknown animal type")
|
工厂函数的优势在于:
- 封装复杂逻辑:隐藏创建对象所需的复杂初始化步骤;
- 运行时类型决定:可以在运行时根据参数决定返回何种子类;
- 返回同一类的多个变种:支持不同配置、不同状态的实例;
- 替代类继承:在某些函数式编程场景中,不用类继承,也可以通过工厂函数生成封装好的行为;
- 支持缓存或单例:结合缓存机制(比如字典)可复用实例。
Usage
数据库连接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class MySQLConnection: def connect(self): return "MySQL connected"
class PostgreSQLConnection: def connect(self): return "PostgreSQL connected"
def db_connection_factory(db_type): if db_type == "mysql": return MySQLConnection() elif db_type == "postgres": return PostgreSQLConnection() else: raise ValueError("Unsupported DB type")
conn = db_connection_factory("mysql") print(conn.connect())
|
工厂函数封装初始化参数
1 2 3 4 5 6 7 8 9 10 11 12
| from datetime import datetime
def create_logger(log_type="file"): if log_type == "file": return lambda msg: print(f"[FILE] {datetime.now()}: {msg}") elif log_type == "console": return lambda msg: print(f"[CONSOLE] {datetime.now()}: {msg}") else: raise ValueError("Unknown log type")
logger = create_logger("console") logger("Something happened")
|
结合缓存,返回单例或共享对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| _instances = {}
def singleton_factory(cls): def get_instance(*args, **kwargs): if cls not in _instances: _instances[cls] = cls(*args, **kwargs) return _instances[cls] return get_instance
@singleton_factory class Configuration: def __init__(self): self.settings = {}
config1 = Configuration() config2 = Configuration()
assert config1 is config2
|
在类中使用工厂函数
现在有一需求,我们想为每个宠物自动分配一个出生时间,给它一个独立的玩具箱(字典),这些值在每次创建时应该不同。
✅ 正确做法:使用default_factory
1 2 3 4 5 6 7 8 9 10
| from dataclasses import dataclass, field from datetime import datetime from typing import Dict
@dataclass class Pet: name: str kind: str born_time: datetime = field(default_factory=datetime.now) toys: Dict[str, int] = field(default_factory=dict)
|
field函数: 使用 field(default_factory=datetime.now) 表示:每次创建 Pet 实例时,都调用 datetime.now() 来自动生成时间戳(不是在类加载时就固定)。
field 是 Python dataclasses 模块中的一个函数,用来给类的属性定义更复杂的行为或默认值。default_factory 是 field() 函数的一个参数,它的作用是指定一个“工厂函数”,每次创建 dataclass 实例时调用它来生成字段的默认值。
1 2 3 4 5 6 7 8 9 10
| cat = Pet(name="Mimi", kind="cat") dog = Pet(name="Doudou", kind="dog")
cat.toys["ball"] = 2
print(cat.born_time) print(dog.born_time) print(dog.toys)
print(cat.toys is dog.toys)
|
❌ 错误示范:不使用default_factory,所有宠物共享玩具箱和出生时间
1 2 3 4 5 6
| @dataclass class BrokenPet: name: str kind: str born_time: datetime = datetime.now() toys: Dict[str, int] = {}
|
1 2 3 4 5 6 7 8
| cat = BrokenPet(name="Mimi", kind="cat") dog = BrokenPet(name="Doudou", kind="dog")
cat.toys["fish"] = 1
print(dog.toys)
print(cat.born_time == dog.born_time)
|
有时人们会混淆类属性和实例属性,导致共享值错误!!!!
工厂方法
厂方法模式(Factory Method Pattern本质是定义一个接口(抽象方法),让子类决定要实例化的类:
- 是 GoF 的正式设计模式之一;
- 基于类继承;
- 通常用在面向对象的架构中;
- Python中可以用 abc(抽象基类)来实现。
一个简单的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| from abc import ABC, abstractmethod
class Animal(ABC): @abstractmethod def speak(self): pass
class Dog(Animal): def speak(self): return "Woof"
class Cat(Animal): def speak(self): return "Meow"
class AnimalFactory(ABC): @abstractmethod def create_animal(self): pass
class DogFactory(AnimalFactory): def create_animal(self): return Dog()
class CatFactory(AnimalFactory): def create_animal(self): return Cat()
factory = DogFactory() animal = factory.create_animal() print(animal.speak())
|
DogFactory 和 CatFactory 继承了 AnimalFactory,并各自实现了创建逻辑。