Python 开发“设计模式”指南

一、前言:为什么 Python 也需要设计模式?

Python 是动态语言,语法灵活,不需要像 Java 那样严格,但在 Python 开发中也需要用到设计模式。虽然 Python 的特性(如一等函数、装饰器、鸭子类型)简化了许多模式的实现,但设计模式的核心思想是"解耦"、"复用"和"可维护性"。在大型项目、团队协作或复杂业务逻辑中,良好的设计模式能避免代码变成一坨...

在 Python 中应用设计模式时,应遵循 KISS (Keep It Simple, Stupid) 原则,不要为了模式而模式。


二、 创建型模式 (Creational Patterns)

创建型模式关注对象的创建过程,将对象的创建与使用分离。

2.1 单例模式 (Singleton)

场景:确保一个类只有一个实例,并提供全局访问点。例如:数据库连接池、配置管理器。

Pythonic 实现 : 在 Python 中,模块本身就是单例的。最简单的单例是直接写在模块里。如果必须用类,可以使用元类或 __new__

复制代码
# 方法一:使用装饰器实现单例
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance
​
@singleton
class Database:
    def __init__(self):
        print("Initializing Database Connection...")
​
db1 = Database()
db2 = Database()
print(db1 is db2)  # True
复制代码
# 方法二:使用元类 (更严谨)
class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super().__call__(*args, **kwargs)
        return cls._instances[cls]
​
class Config(metaclass=SingletonMeta):
    pass

2.2 工厂模式 (Factory)

场景:不需要知道具体类的实例化细节,只需根据参数获取对象。

简单工厂示例

复制代码
class Dog:
    def speak(self): return "Woof!"
​
class Cat:
    def speak(self): return "Meow!"
​
class AnimalFactory:
    @staticmethod
    def get_animal(animal_type):
        if animal_type == 'dog':
            return Dog()
        elif animal_type == 'cat':
            return Cat()
        else:
            raise ValueError("Unknown animal type")
​
# 使用
animal = AnimalFactory.get_animal('dog')
print(animal.speak())

注:Python 中常利用多态和字典映射来简化工厂逻辑,避免大量的 if-else。

2.3 建造者模式 (Builder)

场景:构建复杂对象,步骤固定但内部表示可能变化。例如:构建复杂的 HTTP 请求对象、SQL 查询构建器。

复制代码
class House:
    def __init__(self):
        self.walls = None
        self.roof = None
        self.rooms = None
​
    def __str__(self):
        return f"House with {self.walls} walls, {self.roof} roof, {self.rooms} rooms"
​
class HouseBuilder:
    def __init__(self):
        self.house = House()
​
    def set_walls(self, walls):
        self.house.walls = walls
        return self
​
    def set_roof(self, roof):
        self.house.roof = roof
        return self
    
    def set_rooms(self, rooms):
        self.house.rooms = rooms
        return self
​
    def build(self):
        return self.house
​
# 链式调用
house = HouseBuilder().set_walls(4).set_roof("Tile").set_rooms(3).build()
print(house)

三、 结构型模式 (Structural Patterns)

结构型模式关注类和对象的组合,形成更大的结构。

3.1 装饰器模式 (Decorator)

场景 :动态地给对象添加职责。 Python 特性 :Python 语言原生支持装饰器语法 (@),这是装饰器模式的一等公民。

复制代码
# 函数装饰器
def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper
​
@log_decorator
def say_hello():
    print("Hello")
​
say_hello()
​
# 类装饰器模式 (用于扩展类功能)
class TextField:
    def write(self, text):
        print(text)
​
class BorderDecorator:
    def __init__(self, component):
        self._component = component
    
    def write(self, text):
        print("-----")
        self._component.write(text)
        print("-----")
​
# 使用
text = TextField()
bordered_text = BorderDecorator(text)
bordered_text.write("Content")

3.2 适配器模式 (Adapter)

场景:接口不兼容,需要转换。例如:对接第三方 API,旧代码复用。

复制代码
# 目标接口
class Target:
    def request(self):
        return "Target: The default target's behavior."
​
# 需要适配的类
class Adaptee:
    def specific_request(self):
        return ".eetpaAd ehT :eetpadA"
​
# 适配器
class Adapter(Target):
    def __init__(self, adaptee):
        self.adaptee = adaptee
​
    def request(self):
        return f"Adapter: (TRANSLATED) {self.adaptee.specific_request()[::-1]}"
​
# 使用
adaptee = Adaptee()
adapter = Adapter(adaptee)
print(adapter.request())

3.3 外观模式 (Facade)

场景:为子系统提供统一的入口,降低耦合。例如:封装复杂的视频转换流程。

复制代码
class CPU:
    def freeze(self): print("Freezing CPU")
    def jump(self): print("Jumping to address")
​
class Memory:
    def load(self): print("Loading data")
​
class SSD:
    def read(self): print("Reading from SSD")
​
class ComputerFacade:
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.ssd = SSD()
​
    def start(self):
        print("Starting Computer...")
        self.cpu.freeze()
        self.memory.load()
        self.ssd.read()
        self.cpu.jump()
        print("Computer Started.")
​
# 客户端只需调用一个方法
pc = ComputerFacade()
pc.start()

四、 行为型模式 (Behavioral Patterns)

行为型模式关注对象之间的通信和责任分配。

4.1 策略模式 (Strategy)

场景 :定义一系列算法,把它们封装起来,并使它们可互换。Python 中常利用函数作为参数来简化策略模式。

复制代码
from abc import ABC, abstractmethod
​
# 传统类实现
class Strategy(ABC):
    @abstractmethod
    def execute(self, data):
        pass
​
class ConcreteStrategyA(Strategy):
    def execute(self, data):
        return sorted(data)
​
class ConcreteStrategyB(Strategy):
    def execute(self, data):
        return list(reversed(data))
​
class Context:
    def __init__(self, strategy: Strategy):
        self._strategy = strategy
​
    def set_strategy(self, strategy: Strategy):
        self._strategy = strategy
​
    def run(self, data):
        return self._strategy.execute(data)
​
# Pythonic 实现:直接传入函数
def sort_strategy(data): return sorted(data)
def reverse_strategy(data): return list(reversed(data))
​
def run_strategy(data, strategy_func):
    return strategy_func(data)
​
print(run_strategy([3, 1, 2], sort_strategy))

4.2 观察者模式 (Observer)

场景:对象状态改变时,自动通知依赖对象。事件驱动系统的核心。

复制代码
class Subject:
    def __init__(self):
        self._observers = []
​
    def attach(self, observer):
        self._observers.append(observer)
​
    def notify(self, message):
        for observer in self._observers:
            observer.update(message)
​
class Observer:
    def update(self, message):
        print(f"Received: {message}")
​
# 使用
subject = Subject()
obs1 = Observer()
obs2 = Observer()
​
subject.attach(obs1)
subject.attach(obs2)
subject.notify("New Data Available!")

注:实际生产中推荐使用 pubsub 库或信号量机制(如 Django Signals)。

4.3 模板方法模式 (Template Method)

场景:定义算法骨架,将具体步骤延迟到子类。

复制代码
from abc import ABC, abstractmethod
​
class DataMiner(ABC):
    def mine(self, path):
        self.open_file(path)
        data = self.extract_data()
        self.analyze(data)
        self.close_file()
​
    def open_file(self, path):
        print(f"Opening {path}")
​
    def close_file(self):
        print("Closing file")
​
    @abstractmethod
    def extract_data(self):
        pass
​
    @abstractmethod
    def analyze(self, data):
        pass
​
class CSVMiner(DataMiner):
    def extract_data(self):
        print("Extracting CSV data")
        return "csv_data"
​
    def analyze(self, data):
        print(f"Analyzing {data}")
​
# 使用
miner = CSVMiner()
miner.mine("data.csv")

五、 Python 特有的"模式"与注意事项

在 Python 中应用设计模式,必须考虑语言特性,否则会产生"反模式"。

  1. 模块即单例 : 不需要写复杂的单例类。创建一个 config.py 模块,在其他地方 import config,该模块内的变量就是全局单例的。

  2. 鸭子类型 (Duck Typing) : 不需要严格的接口继承(Interface)。只要对象有 read() 方法,它就是文件流。这减少了对适配器模式的部分需求。

  3. 一等函数 : 策略模式、命令模式在 Python 中通常直接传递函数或 lambda,而不是创建一堆策略类。

  4. 装饰器语法 : 日志、权限校验、缓存等功能,优先使用 @decorator,而不是手动实现装饰器模式类。

  5. 避免过度设计YAGNI (You Ain't Gonna Need It)。如果代码只有 50 行,不要强行套用工厂模式。当复制粘贴代码超过 3 次,或者逻辑变得难以测试时,再考虑重构引入模式。


六、总结与建议

设计模式不是银弹,而是工具箱。

  • 初级开发者:先理解代码逻辑,能写出功能正确的代码。

  • 中级开发者:识别代码中的"坏味道"(如重复代码、高耦合),尝试用简单的模式(如策略、装饰器)重构。

  • 高级开发者 :根据业务场景权衡,知道什么时候不使用模式同样重要。

推荐学习路径

  1. 阅读《Python 设计模式》(相关书籍)。

  2. 阅读优秀开源项目源码(如 Requests, Flask, Django),看它们如何运用模式。

  3. 在实际项目中小步重构,不要一次性重写。

相关推荐
梦想的初衷~1 小时前
无人机多光谱-生态三维建模全流程实战——基于Python与AI辅助技术
人工智能·python·无人机·生态·遥感·多光谱
MadPrinter1 小时前
Attention Residuals 代码实现:从原理到 PyTorch 实战(第 2 篇)
人工智能·pytorch·python·ai·自动化·openclaw
JMet1 小时前
AI测试用例生成脚本
人工智能·python·源码
大叔_爱编程1 小时前
基于协同过滤算法的理财产品推荐系统-flask
python·flask·vue·毕业设计·源码·课程设计·协同过滤
2401_884970612 小时前
用Pygame开发你的第一个小游戏
jvm·数据库·python
wertyuytrewm2 小时前
用Python实现自动化的Web测试(Selenium)
jvm·数据库·python
曲辕RPA2 小时前
深度解析GEO技术及背后的机器人曲辕RPA
python·ai·自动化·rpa