Python设计模式终极指南:18种模式详解+正反案例对比+框架源码剖析

发布于:2025-06-21 ⋅ 阅读:(19) ⋅ 点赞:(0)

下面我将全面解析18种Python设计模式,每种模式都包含实际应用场景、优缺点分析、框架引用案例、可运行代码示例以及正反案例对比,帮助您深入理解设计模式的价值。

一、创建型模式(5种)

1. 单例模式(Singleton)

场景:数据库连接池、全局配置管理
优点:资源复用,保证全局一致性
缺点:违反单一职责,多线程需同步
框架应用:Django配置对象 django.conf.settings

class DatabaseConnection:
    _instance = None
    
    def __new__(cls):
        if not cls._instance:
            cls._instance = super().__new__(cls)
            # 模拟数据库连接初始化
            print("创建新的数据库连接(昂贵操作)")
        return cls._instance

# 正面示例
db1 = DatabaseConnection()
db2 = DatabaseConnection()
print(db1 is db2)  # True,复用同一连接

# 反面示例(无单例)
class BadDatabase:
    def __init__(self):
        print("创建新的数据库连接(昂贵操作)")

db3 = BadDatabase()
db4 = BadDatabase()  # 重复创建连接,浪费资源

2. 工厂方法模式(Factory Method)

场景:支付网关切换、日志处理器选择
优点:解耦客户端和具体类
缺点:增加代码复杂度

from abc import ABC, abstractmethod

class PaymentGateway(ABC):
    @abstractmethod
    def pay(self, amount): pass

class StripeGateway(PaymentGateway):
    def pay(self, amount): 
        print(f"Stripe支付 ${amount}")

class PayPalGateway(PaymentGateway):
    def pay(self, amount): 
        print(f"PayPal支付 ${amount}")

def payment_factory(gateway_type):
    if gateway_type == "stripe": return StripeGateway()
    if gateway_type == "paypal": return PayPalGateway()
    raise ValueError("无效支付网关")

# 正面示例
payment = payment_factory("stripe")
payment.pay(100)  # 客户端无需知道具体实现类

# 反面示例(硬编码依赖)
class OrderProcessor:
    def process_payment(self, amount):
        gateway = StripeGateway()  # 直接依赖具体类
        gateway.pay(amount)
        
# 更换支付网关需修改源码

3. 抽象工厂模式(Abstract Factory)

场景:跨平台UI组件库
优点:确保产品兼容性
缺点:扩展新产品困难

class Button(ABC):
    @abstractmethod
    def render(self): pass

class WindowsButton(Button):
    def render(self): print("Windows风格按钮")

class MacButton(Button):
    def render(self): print("Mac风格按钮")

class GUIFactory(ABC):
    @abstractmethod
    def create_button(self): pass

class WindowsFactory(GUIFactory):
    def create_button(self): return WindowsButton()

class MacFactory(GUIFactory):
    def create_button(self): return MacButton()

# 正面示例
def create_ui(os_type):
    factory = WindowsFactory() if os_type == "windows" else MacFactory()
    button = factory.create_button()
    button.render()  # 自动匹配操作系统风格

# 反面示例(平台相关代码分散)
if os_type == "windows":
    button = WindowsButton()
elif os_type == "mac":
    button = MacButton()
button.render()
# 添加新平台需修改多处条件判断

4. 建造者模式(Builder)

场景:复杂对象创建(如SQL查询)
优点:分离构造过程与表示
缺点:增加额外Builder类


class SQLQuery:
    def __init__(self):
        self.table = ""
        self.fields = []
        self.where_clauses = []
    
    def execute(self):
        fields = ", ".join(self.fields) or "*"
        where = (" WHERE " + " AND ".join(self.where_clauses)) if self.where_clauses else ""
        print(f"SELECT {fields} FROM {self.table}{where}")

class QueryBuilder:
    def __init__(self):
        self.query = SQLQuery()
    
    def select(self, *fields):
        self.query.fields = fields
        return self
    
    def from_table(self, table):
        self.query.table = table
        return self
    
    def where(self, condition):
        self.query.where_clauses.append(condition)
        return self
    
    def build(self):
        return self.query

# 正面示例
query = (QueryBuilder()
        .select("id", "name")
        .from_table("users")
        .where("age > 18")
        .build())
query.execute()

# 反面示例(构造参数爆炸)
class BadQuery:
    def __init__(self, table, fields=None, where=None, joins=None, group_by=None):
        # 参数过多难以维护
        self.table = table
        self.fields = fields or []
        self.where = where or []
        # ...更多参数

5. 原型模式(Prototype)

场景:游戏对象克隆、配置模板
优点:避免重复初始化开销
缺点:深拷贝可能复杂


import copy

class NPC:
    def __init__(self, name, health, position):
        self.name = name
        self.health = health
        self.position = position
        # 模拟昂贵初始化
        print(f"创建NPC {name}(耗时操作)")
    
    def clone(self):
        return copy.deepcopy(self)

# 正面示例
orc_template = NPC("兽人", 100, (0, 0))
orc1 = orc_template.clone()  # 快速克隆
orc1.position = (10, 5)

# 反面示例(重复初始化)
orc2 = NPC("兽人", 100, (0, 0))  # 重复执行昂贵初始化

二、结构型模式(6种)

6. 适配器模式(Adapter)

场景:整合第三方库、旧系统接口改造
优点:解决接口不兼容问题
缺点:增加额外层


class LegacyLogger:
    def log_message(self, msg, priority):
        print(f"[{priority}] {msg}")

class ModernLogger:
    def log(self, message, level="INFO"):
        print(f"{level}: {message}")

class LoggerAdapter:
    def __init__(self, logger):
        self.logger = logger
    
    def log(self, message, level="INFO"):
        if isinstance(self.logger, LegacyLogger):
            # 转换接口
            priority = 1 if level == "ERROR" else 0
            self.logger.log_message(message, priority)
        else:
            self.logger.log(message, level)

# 正面示例
legacy = LoggerAdapter(LegacyLogger())
legacy.log("系统错误", level="ERROR")  # 自动转换接口

# 反面示例(直接修改第三方库)
# 修改LegacyLogger源码使其兼容ModernLogger接口 → 违反开闭原则

7. 装饰器模式(Decorator)

场景:功能扩展(日志、缓存、权限)
优点:动态添加功能,符合开闭原则
缺点:多层装饰可读性下降
框架应用:Flask路由装饰器 @app.route


def log_execution(func):
    def wrapper(*args, **kwargs):
        print(f"执行: {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

def cache_result(func):
    cache = {}
    def wrapper(*args):
        if args in cache:
            print("返回缓存结果")
            return cache[args]
        result = func(*args)
        cache[args] = result
        return result
    return wrapper

@log_execution
@cache_result
def fibonacci(n):
    if n <= 1: return n
    return fibonacci(n-1) + fibonacci(n-2)

# 正面示例
print(fibonacci(10))  # 带日志和缓存

# 反面示例(硬编码功能)
def bad_fibonacci(n):
    print(f"执行: bad_fibonacci")  # 日志硬编码
    # ...实现+缓存逻辑混合...

8. 代理模式(Proxy)

场景:延迟加载、访问控制
优点:控制对象访问,实现懒加载
缺点:增加响应时间


class HighResImage:
    def __init__(self, filename):
        self.filename = filename
        self._load_image()
    
    def _load_image(self):
        print(f"加载高清图片: {self.filename}(耗时操作)")
    
    def display(self): 
        print(f"显示: {self.filename}")

class ImageProxy:
    def __init__(self, filename):
        self.filename = filename
        self._real_image = None
    
    def display(self):
        if not self._real_image:
            self._real_image = HighResImage(self.filename)
        self._real_image.display()

# 正面示例
gallery = [ImageProxy(f"image{i}.jpg") for i in range(3)]
gallery[0].display()  # 仅加载第一张

# 反面示例(提前加载所有资源)
images = [HighResImage(f"image{i}.jpg") for i in range(3)]  # 启动时全部加载

9. 外观模式(Facade)

场景:简化复杂子系统调用
优点:提供统一接口,降低耦合
缺点:可能成为"上帝对象"


class CPU:
    def process(self): print("CPU处理数据")

class Memory:
    def load(self): print("内存加载数据")

class HardDrive:
    def read(self): print("硬盘读取数据")

class Computer:
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.hd = HardDrive()
    
    def start(self):
        self.hd.read()
        self.memory.load()
        self.cpu.process()

# 正面示例
pc = Computer()
pc.start()  # 简单调用接口

# 反面示例(客户端直接调用子系统)
hd = HardDrive()
mem = Memory()
cpu = CPU()
hd.read()
mem.load()
cpu.process()  # 客户端需了解所有细节

10. 享元模式(Flyweight)

场景:文本编辑器字符格式
优点:大幅减少内存使用
缺点:增加代码复杂度


class CharacterStyle:
    _cache = {}
    
    def __new__(cls, font, size, color):
        key = (font, size, color)
        if key not in cls._cache:
            cls._cache[key] = super().__new__(cls)
            cls._cache[key].font = font
            cls._cache[key].size = size
            cls._cache[key].color = color
        return cls._cache[key]

class Document:
    def __init__(self):
        self.chars = []
    
    def add_char(self, char, font, size, color):
        style = CharacterStyle(font, size, color)
        self.chars.append((char, style))
    
    def render(self):
        for char, style in self.chars:
            print(f"渲染 '{char}' 使用 {style.font}")

# 正面示例(1000个字符只创建2种样式)
doc = Document()
for _ in range(500):
    doc.add_char('A', "Arial", 12, "black")
for _ in range(500):
    doc.add_char('B', "Times", 14, "blue")
print(f"样式实例数: {len(CharacterStyle._cache)}")  # 2

# 反面示例(重复创建样式)
class BadChar:
    def __init__(self, char, font, size, color):
        self.char = char
        self.font = font
        # 每个字符独立存储样式 → 内存浪费

三、行为型模式(7种)

11. 观察者模式(Observer)

场景:事件通知、消息订阅
优点:解耦发布者和订阅者
缺点:意外更新链
框架应用:Django Signals


class Newsletter:
    def __init__(self):
        self.subscribers = []
    
    def subscribe(self, subscriber):
        self.subscribers.append(subscriber)
    
    def unsubscribe(self, subscriber):
        self.subscribers.remove(subscriber)
    
    def publish(self, news):
        print(f"发布新闻: {news}")
        for sub in self.subscribers:
            sub.notify(news)

class Subscriber:
    def notify(self, news):
        print(f"{self.name} 收到: {news}")

class EmailSubscriber(Subscriber):
    def __init__(self, name):
        self.name = f"邮箱用户-{name}"

class AppSubscriber(Subscriber):
    def __init__(self, name):
        self.name = f"APP用户-{name}"

# 正面示例
newsletter = Newsletter()
newsletter.subscribe(EmailSubscriber("张三"))
newsletter.subscribe(AppSubscriber("李四"))
newsletter.publish("Python 3.12发布")

# 反面示例(紧耦合)
class BadNewsletter:
    def publish(self, news):
        print(f"发布新闻: {news}")
        # 直接调用具体方法
        EmailSubscriber("张三").notify(news)
        AppSubscriber("李四").notify(news)

12. 策略模式(Strategy)

场景:支付方式选择、排序算法
优点:运行时切换算法
缺点:客户端需了解不同策略


class CompressionStrategy(ABC):
    @abstractmethod
    def compress(self, file): pass

class ZipStrategy(CompressionStrategy):
    def compress(self, file):
        print(f"ZIP压缩 {file}(压缩率高)")

class RarStrategy(CompressionStrategy):
    def compress(self, file):
        print(f"RAR压缩 {file}(加密支持)")

class Compressor:
    def __init__(self, strategy=None):
        self.strategy = strategy or ZipStrategy()
    
    def set_strategy(self, strategy):
        self.strategy = strategy
    
    def compress_file(self, file):
        self.strategy.compress(file)

# 正面示例
compressor = Compressor()
compressor.compress_file("data.txt")

compressor.set_strategy(RarStrategy())
compressor.compress_file("data.txt")  # 动态切换算法

# 反面示例(条件分支判断)
class BadCompressor:
    def compress(self, file, method="zip"):
        if method == "zip":
            print(f"ZIP压缩 {file}")
        elif method == "rar":
            print(f"RAR压缩 {file}")
        # 添加新算法需修改源码

13. 模板方法模式(Template Method)

场景:算法框架定义
优点:代码复用,扩展性好
缺点:可能限制灵活性
框架应用:Django类视图 View.dispatch()


class ReportGenerator(ABC):
    def generate(self):
        self.collect_data()
        self.process_data()
        self.export()
    
    @abstractmethod
    def collect_data(self): pass
    
    def process_data(self):
        print("通用数据处理")
    
    @abstractmethod
    def export(self): pass

class PDFReport(ReportGenerator):
    def collect_data(self):
        print("收集PDF数据")
    
    def export(self):
        print("导出PDF文档")

class ExcelReport(ReportGenerator):
    def collect_data(self):
        print("收集Excel数据")
    
    def process_data(self):
        print("自定义Excel数据处理")
    
    def export(self):
        print("导出Excel文件")

# 正面示例
pdf = PDFReport()
pdf.generate()  # 复用通用流程

# 反面示例(重复代码)
class BadPDFReport:
    def generate(self):
        print("收集PDF数据")
        print("通用数据处理")  # 重复代码
        print("导出PDF文档")

class BadExcelReport:
    def generate(self):
        print("收集Excel数据")
        print("通用数据处理")  # 重复代码
        print("导出Excel文件")

14. 责任链模式(Chain of Responsibility)

场景:请求处理管道、中间件
优点:动态添加处理者
缺点:请求可能未处理
框架应用:Django中间件系统


class Handler(ABC):
    def __init__(self, successor=None):
        self.successor = successor
    
    def handle(self, request):
        if self.can_handle(request):
            return self.process(request)
        elif self.successor:
            return self.successor.handle(request)
        raise Exception("无法处理请求")
    
    @abstractmethod
    def can_handle(self, request): pass
    
    @abstractmethod
    def process(self, request): pass

class AuthHandler(Handler):
    def can_handle(self, request):
        return "auth" in request
    
    def process(self, request):
        print("身份验证通过")

class LogHandler(Handler):
    def can_handle(self, request):
        return True  # 最终处理器
    
    def process(self, request):
        print(f"记录请求: {request}")

# 正面示例
pipeline = AuthHandler(LogHandler())
pipeline.handle({"action": "login", "auth": "token"})

# 反面示例(巨型处理函数)
def bad_handler(request):
    if "auth" in request:
        print("身份验证通过")
    # ...其他条件分支...
    print(f"记录请求: {request}")  # 所有逻辑耦合

15. 命令模式(Command)

场景:GUI操作、事务管理
优点:解耦调用者和接收者
缺点:增加命令类数量


class Light:
    def on(self): print("开灯")
    def off(self): print("关灯")

class Command(ABC):
    @abstractmethod
    def execute(self): pass

class LightOnCommand(Command):
    def __init__(self, light):
        self.light = light
    
    def execute(self):
        self.light.on()

class LightOffCommand(Command):
    def __init__(self, light):
        self.light = light
    
    def execute(self):
        self.light.off()

class RemoteControl:
    def __init__(self):
        self.history = []
    
    def execute_command(self, command):
        command.execute()
        self.history.append(command)
    
    def undo(self):
        if self.history:
            last = self.history.pop()
            print("撤销操作: ", end="")
            last.execute()  # 简化:实际需实现反向操作

# 正面示例
light = Light()
remote = RemoteControl()
remote.execute_command(LightOnCommand(light))
remote.undo()  # 支持撤销

# 反面示例(直接调用)
light.on()  # 无法记录历史,不支持撤销

16. 状态模式(State)

场景:订单状态流转、游戏角色状态
优点:简化状态转换逻辑
缺点:增加状态类数量


class OrderState(ABC):
    @abstractmethod
    def next(self, order): pass
    
    @abstractmethod
    def prev(self, order): pass

class PendingState(OrderState):
    def next(self, order):
        order.state = PaidState()
    
    def prev(self, order):
        print("已是初始状态")

class PaidState(OrderState):
    def next(self, order):
        order.state = ShippedState()
    
    def prev(self, order):
        order.state = PendingState()

class Order:
    def __init__(self):
        self.state = PendingState()
    
    def next_state(self):
        print("转到下一状态")
        self.state.next(self)
    
    def __str__(self):
        return type(self.state).__name__

# 正面示例
order = Order()
print(order)  # PendingState
order.next_state()
print(order)  # PaidState

# 反面示例(状态标志+条件分支)
class BadOrder:
    def __init__(self):
        self.status = "pending"
    
    def next_state(self):
        if self.status == "pending":
            self.status = "paid"
        elif self.status == "paid":
            self.status = "shipped"
        # 状态逻辑分散在各处

四、Python设计模式深度洞察

1.动态语言特性:Python的鸭子类型减少了对工厂模式的需求

2.装饰器内置支持:@decorator语法是装饰器模式的语法糖

3.模式混合使用:实际项目中常组合多种模式(如Observer + Command)

4.框架设计启示:

    Django使用Template Method定义视图生命周期

    Flask通过Decorator实现路由注册

    SQLAlchemy的Session使用Proxy模式

五、为什么需要设计模式?—— 未使用模式的代价

问题场景 无模式方案 后果 适用模式
全局配置管理 多个独立配置对象 配置不一致,资源浪费 单例模式
多支付网关支持 if/else硬编码 添加新网关需修改核心逻辑 策略模式
跨平台UI开发 平台相关代码分散 维护困难,兼容性问题 抽象工厂
复杂对象构造 超长构造函数 参数混乱,构造逻辑复杂 建造者模式
事件通知系统 直接调用接收方 紧耦合,难以扩展新接收方 观察者模式

网站公告

今日签到

点亮在社区的每一天
去签到