技术博客-导航条

Python 常用设计模式实战:从原理到代码落地

设计模式是软件开发中解决共性问题的成熟方案,就像编程世界的 “通用模板”—— 无需重复造轮子,就能写出灵活、可维护、易扩展的代码。GoF(四人帮)定义的 23 种设计模式是行业标杆,其中不少模式在 Python 开发中高频出现。本文将聚焦最实用的设计模式,用 “生活类比 + Python 代码” 的方式拆解核心逻辑,帮你快速掌握并落地到实际项目中。

一、创建型模式:优雅管理对象创建

创建型模式的核心是 “分离对象创建与使用”,避免硬编码导致的耦合,让对象创建更灵活。

1. 单例模式:确保唯一实例

  • 核心思想:一个类只能创建一个实例,同时提供全局统一的访问入口。
  • 生活类比:国家只有一个首都、APP 只有一个全局配置对象,无法重复创建。
  • 适用场景:数据库连接池、日志记录器、全局配置、线程池(避免资源浪费)。
  • Python 实现(懒加载版)

python

运行

class Singleton:
    # 私有类属性,存储唯一实例
    __instance = None

    def __new__(cls):
        # 首次创建时初始化实例,后续直接返回已有实例
        if not cls.__instance:
            cls.__instance = super().__new__(cls)
            # 初始化全局配置(仅执行一次)
            cls.__instance.config = {"timeout": 30, "encoding": "utf-8"}
        return cls.__instance

# 测试:多次实例化结果一致
obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2)  # 输出:True(同一实例)
obj1.config["timeout"] = 60
print(obj2.config["timeout"])  # 输出:60(共享属性)

2. 工厂方法模式:延迟实例化到子类

  • 核心思想:定义创建对象的接口,让子类决定具体实例化哪个类,实现 “创建逻辑” 与 “使用逻辑” 分离。
  • 生活类比:家具厂(父类)定义 “制作家具” 接口,椅子厂、桌子厂(子类)分别实现该接口,生产具体产品。
  • 适用场景:日志输出(控制台 / 文件 / 数据库)、数据库连接(MySQL/PostgreSQL)、支付渠道对接。
  • Python 实现(日志工厂)

python

运行

# 抽象产品:日志接口
class Logger:
    def log(self, message):
        raise NotImplementedError("子类必须实现log方法")

# 具体产品1:控制台日志
class ConsoleLogger(Logger):
    def log(self, message):
        print(f"[控制台] {message}")

# 具体产品2:文件日志
class FileLogger(Logger):
    def log(self, message):
        with open("app.log", "a", encoding="utf-8") as f:
            f.write(f"[文件] {message}\n")

# 工厂方法:日志工厂
class LoggerFactory:
    def create_logger(self, type_):
        if type_ == "console":
            return ConsoleLogger()
        elif type_ == "file":
            return FileLogger()
        else:
            raise ValueError("不支持的日志类型")

# 使用示例
factory = LoggerFactory()
console_logger = factory.create_logger("console")
file_logger = factory.create_logger("file")
console_logger.log("用户登录成功")  # 控制台输出
file_logger.log("系统启动完成")      # 写入文件

3. 建造者模式:分步构建复杂对象

  • 核心思想:将复杂对象的构建流程与组件细节分离,相同流程可创建不同配置的对象。
  • 生活类比:组装电脑,流程固定(装 CPU→内存→硬盘→显卡),但可选择不同品牌、配置的组件,最终得到高配 / 低配电脑。
  • 适用场景:SQL 查询构建、邮件对象组装、复杂配置类创建。
  • Python 实现(SQL 构建器)

python

运行

class SQLBuilder:
    def __init__(self):
        self.sql = ""
        self.select_clause = ""
        self.from_clause = ""
        self.where_clause = ""

    # 步骤1:设置查询字段
    def select(self, fields):
        self.select_clause = f"SELECT {','.join(fields)}"
        return self  # 链式调用

    # 步骤2:设置表名
    def from_table(self, table):
        self.from_clause = f"FROM {table}"
        return self

    # 步骤3:设置查询条件
    def where(self, condition):
        self.where_clause = f"WHERE {condition}"
        return self

    # 步骤4:构建最终SQL
    def build(self):
        self.sql = f"{self.select_clause} {self.from_clause} {self.where_clause}"
        return self.sql

# 使用示例:链式构建SQL
sql = SQLBuilder()\
    .select(["id", "name", "age"])\
    .from_table("users")\
    .where("age > 18")\
    .build()
print(sql)  # 输出:SELECT id,name,age FROM users WHERE age > 18

二、结构型模式:灵活组合类与对象

结构型模式关注 “如何将类或对象组合成更复杂的结构”,同时保持结构的灵活性和可扩展性。

1. 适配器模式:解决接口不兼容问题

  • 核心思想:将一个类的接口转换成客户端期望的另一个接口,让原本无法协作的类能够一起工作。
  • 生活类比:电源转接头,中国插头(旧接口)通过转接头适配欧洲插座(新接口)。
  • 适用场景:整合遗留系统、第三方库接口适配、旧代码重构。
  • Python 实现(支付接口适配)

python

运行

# 第三方支付库(旧接口,无法修改)
class AlipayOld:
    def pay_old(self, amount):
        return f"支付宝旧接口支付 {amount} 元"

# 客户端期望的统一接口(新接口)
class PaymentInterface:
    def pay(self, amount):
        raise NotImplementedError("必须实现pay方法")

# 适配器:将支付宝旧接口适配到新接口
class AlipayAdapter(PaymentInterface):
    def __init__(self, alipay_old):
        self.alipay_old = alipay_old

    def pay(self, amount):
        # 适配旧接口方法到新接口
        return self.alipay_old.pay_old(amount)

# 使用示例:客户端统一调用新接口
old_alipay = AlipayOld()
adapter = AlipayAdapter(old_alipay)
print(adapter.pay(100))  # 输出:支付宝旧接口支付 100 元

2. 装饰器模式:动态添加对象功能

  • 核心思想:不改变原对象结构,动态给对象添加额外职责,比继承更灵活(可自由组合功能)。
  • 生活类比:给手机贴钢化膜(防刮)、戴保护壳(防摔)、挂挂件(装饰),不改变手机本身,却增加了新功能。
  • 适用场景:日志记录、性能监控、权限校验、数据缓存。
  • Python 实现(函数装饰器)

python

运行

import time

# 装饰器1:记录函数执行日志
def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"[日志] 执行函数 {func.__name__}")
        result = func(*args, **kwargs)
        print(f"[日志] 函数 {func.__name__} 执行完成")
        return result
    return wrapper

# 装饰器2:统计函数执行时间
def time_decorator(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"[耗时] 函数 {func.__name__} 执行时间:{end - start:.2f}秒")
        return result
    return wrapper

# 组合装饰器:给函数同时添加日志和耗时统计功能
@log_decorator
@time_decorator
def calculate_sum(n):
    return sum(range(1, n+1))

# 使用示例
print(calculate_sum(1000000))
# 输出:
# [日志] 执行函数 calculate_sum
# [耗时] 函数 calculate_sum 执行时间:0.04秒
# [日志] 函数 calculate_sum 执行完成
# 500000500000

3. 外观模式:简化复杂子系统调用

  • 核心思想:为复杂子系统提供一个统一的高层接口,隐藏内部细节,让客户端调用更简单。
  • 生活类比:餐厅服务员,客户无需直接对接后厨、收银台、采购部,只需告诉服务员需求,由服务员协调内部流程。
  • 适用场景:简化复杂库调用、遗留系统封装、微服务接口聚合。
  • Python 实现(订单处理系统)

python

运行

# 复杂子系统1:库存检查
class InventoryService:
    def check_stock(self, product_id, quantity):
        print(f"检查商品 {product_id} 库存,需 {quantity} 件")
        return True  # 假设库存充足

# 复杂子系统2:支付处理
class PaymentService:
    def process_payment(self, user_id, amount):
        print(f"用户 {user_id} 支付 {amount} 元")
        return True  # 假设支付成功

# 复杂子系统3:物流下单
class LogisticsService:
    def create_order(self, product_id, user_id):
        print(f"为用户 {user_id} 创建商品 {product_id} 物流单")
        return "物流单号:LOG123456"

# 外观类:统一订单处理接口
class OrderFacade:
    def __init__(self):
        self.inventory = InventoryService()
        self.payment = PaymentService()
        self.logistics = LogisticsService()

    def place_order(self, user_id, product_id, quantity, amount):
        # 协调子系统流程
        if not self.inventory.check_stock(product_id, quantity):
            return "库存不足,下单失败"
        if not self.payment.process_payment(user_id, amount):
            return "支付失败,下单失败"
        logistics_no = self.logistics.create_order(product_id, user_id)
        return f"下单成功!{logistics_no}"

# 使用示例:客户端只需调用外观类接口
facade = OrderFacade()
result = facade.place_order(user_id=1001, product_id=2001, quantity=2, amount=299)
print(result)  # 输出:下单成功!物流单号:LOG123456

三、行为型模式:优化对象间通信与职责

行为型模式关注 “对象间的职责分配” 和 “通信方式”,让对象协作更高效、灵活。

1. 观察者模式:一对多的通知机制

  • 核心思想:定义对象间的一对多依赖关系,当一个对象(主题)状态变化时,所有依赖它的对象(观察者)会自动收到通知并更新。
  • 生活类比:微信公众号(主题)与订阅用户(观察者),公众号发布新文章时,所有订阅用户都会收到推送。
  • 适用场景:事件驱动系统、MVC 模式(模型 – 视图)、消息通知、状态同步。
  • Python 实现(消息通知系统)

python

运行

class Subject:
    def __init__(self):
        self.observers = []  # 存储所有观察者

    # 注册观察者
    def attach(self, observer):
        self.observers.append(observer)

    # 移除观察者
    def detach(self, observer):
        self.observers.remove(observer)

    # 通知所有观察者
    def notify(self, message):
        for observer in self.observers:
            observer.update(message)

# 观察者1:邮件通知
class EmailObserver:
    def __init__(self, email):
        self.email = email

    def update(self, message):
        print(f"向 {self.email} 发送邮件通知:{message}")

# 观察者2:短信通知
class SmsObserver:
    def __init__(self, phone):
        self.phone = phone

    def update(self, message):
        print(f"向 {self.phone} 发送短信通知:{message}")

# 使用示例
subject = Subject()
# 注册观察者
subject.attach(EmailObserver("user1@example.com"))
subject.attach(SmsObserver("13800138000"))
# 主题状态变化,通知所有观察者
subject.notify("您的订单已发货!")
# 输出:
# 向 user1@example.com 发送邮件通知:您的订单已发货!
# 向 13800138000 发送短信通知:您的订单已发货!

2. 策略模式:封装可替换的算法

  • 核心思想:定义一系列算法,将每个算法封装起来,并且使它们可以相互替换,算法独立于使用它的客户端。
  • 生活类比:出行导航,可选择 “最快路线”“最短路线”“避开高速” 等策略,用户按需切换,无需关心路线计算细节。
  • 适用场景:支付方式(支付宝 / 微信 / 信用卡)、排序算法、数据验证规则、搜索策略。
  • Python 实现(支付策略)

python

运行

# 抽象策略:支付接口
class PaymentStrategy:
    def pay(self, amount):
        raise NotImplementedError("必须实现支付方法")

# 具体策略1:支付宝支付
class AlipayStrategy(PaymentStrategy):
    def pay(self, amount):
        return f"通过支付宝支付 {amount} 元,已优惠 5 元"

# 具体策略2:微信支付
class WechatPayStrategy(PaymentStrategy):
    def pay(self, amount):
        return f"通过微信支付 {amount} 元,赠送积分 10 点"

# 具体策略3:信用卡支付
class CreditCardStrategy(PaymentStrategy):
    def pay(self, amount):
        return f"通过信用卡支付 {amount} 元,分期免息"

# 上下文:统一支付入口
class PaymentContext:
    def __init__(self, strategy):
        self.strategy = strategy  # 注入具体策略

    # 切换策略
    def set_strategy(self, strategy):
        self.strategy = strategy

    # 执行支付
    def execute_pay(self, amount):
        return self.strategy.pay(amount)

# 使用示例
context = PaymentContext(AlipayStrategy())
print(context.execute_pay(200))  # 输出:通过支付宝支付 200 元,已优惠 5 元

# 切换为微信支付策略
context.set_strategy(WechatPayStrategy())
print(context.execute_pay(200))  # 输出:通过微信支付 200 元,赠送积分 10 点

3. 模板方法模式:固定算法骨架

  • 核心思想:定义一个算法的骨架流程,将某些步骤延迟到子类中实现,子类可重写特定步骤,但不改变算法整体结构。
  • 生活类比:冲泡饮料的流程(烧水→加原料→冲泡→加调料),泡茶和泡咖啡只需改变 “原料” 和 “调料”,流程保持不变。
  • 适用场景:框架设计、重复流程封装(如数据导出、测试用例执行)。
  • Python 实现(数据导出模板)

python

运行

# 抽象模板:数据导出骨架
class DataExporter:
    def export(self, data):
        """模板方法:固定导出流程"""
        self.validate_data(data)  # 步骤1:验证数据(固定)
        self.process_data(data)   # 步骤2:处理数据(子类实现)
        self.save_data(data)      # 步骤3:保存数据(子类实现)
        self.notify_result()      # 步骤4:通知结果(固定)
        return "导出完成"

    def validate_data(self, data):
        """固定步骤:验证数据合法性"""
        if not isinstance(data, dict):
            raise ValueError("数据必须是字典类型")
        print("数据验证通过")

    def process_data(self, data):
        """抽象步骤:子类实现数据处理"""
        raise NotImplementedError("子类必须实现数据处理方法")

    def save_data(self, data):
        """抽象步骤:子类实现数据保存"""
        raise NotImplementedError("子类必须实现数据保存方法")

    def notify_result(self):
        """固定步骤:通知导出结果"""
        print("导出结果已通知管理员")

# 具体模板1:CSV导出
class CsvExporter(DataExporter):
    def process_data(self, data):
        print("将数据转换为CSV格式")

    def save_data(self, data):
        print("保存CSV文件到本地")

# 具体模板2:JSON导出
class JsonExporter(DataExporter):
    def process_data(self, data):
        print("将数据转换为JSON格式")

    def save_data(self, data):
        print("上传JSON文件到服务器")

# 使用示例
csv_exporter = CsvExporter()
print(csv_exporter.export({"name": "测试数据", "value": 100}))
# 输出:
# 数据验证通过
# 将数据转换为CSV格式
# 保存CSV文件到本地
# 导出结果已通知管理员
# 导出完成

json_exporter = JsonExporter()
print(json_exporter.export({"name": "测试数据", "value": 100}))
# 输出:
# 数据验证通过
# 将数据转换为JSON格式
# 上传JSON文件到服务器
# 导出结果已通知管理员
# 导出完成

四、设计模式核心总结与使用原则

1. 常用模式速查表

模式类型模式名称核心作用一句话使用场景
创建型单例模式确保唯一实例全局配置、连接池
创建型工厂方法延迟实例化多类型对象创建(如多数据库连接)
创建型建造者模式分步构建复杂对象SQL 构建、复杂配置组装
结构型适配器模式接口适配整合旧系统、第三方库
结构型装饰器模式动态添加功能日志、缓存、权限校验
结构型外观模式简化子系统调用复杂系统封装、接口聚合
行为型观察者模式一对多通知事件驱动、消息通知
行为型策略模式算法替换支付方式、排序算法
行为型模板方法固定算法骨架框架设计、重复流程封装

2. 关键使用原则

  • 不要为了用模式而用模式:模式是解决问题的工具,而非代码 “炫技” 的手段。
  • 优先简化,再用模式:简单问题直接写代码,复杂问题(需扩展、复用)再考虑模式。
  • 理解本质,灵活变通:Python 中无需严格遵循设计模式的 “类结构”,可结合语言特性(如装饰器语法、动态类型)简化实现。

设计模式的核心价值是 “解耦” 和 “复用”,掌握这些常用模式后,面对复杂业务场景时能快速给出合理的代码结构设计,让项目更易维护、扩展。建议先从单例、装饰器、观察者这几个高频模式入手,在实际项目中尝试应用,逐步积累经验。