设计模式

设计模式

设计模式是软件开发中经过验证的、可复用的解决方案模板,源自 GoF(Gang of Four)的经典著作《设计模式:可复用面向对象软件的基础》。

为什么需要设计模式

  • 复用成熟经验,避免重复设计
  • 提供通用词汇,便于团队沟通
  • 提高代码可读性、可维护性、可扩展性
  • 降低系统耦合,增强灵活性

设计模式分类(23 种 GoF 模式)

创建型(5): 工厂方法、抽象工厂、单例、建造者、原型
结构型(7): 适配器、装饰器、代理、外观、桥接、组合、享元
行为型(11): 观察者、策略、命令、模板方法、迭代器、
          责任链、状态、访问者、中介者、备忘录、解释器

设计原则

开闭原则: 对扩展开放,对修改关闭
单一职责: 一个类只做一件事
里氏替换: 子类可替换父类
接口隔离: 用多个专门接口替代大接口
依赖倒置: 依赖抽象,不依赖具体实现
最少知识: 不与陌生人通信

本教程

后续章节用 Python 实现 23 种经典设计模式,每种都附完整代码与适用场景。

Python 设计模式

Python 设计模式

Python 的鸭子类型、动态特性与一等函数让设计模式的实现更简洁,有些甚至"天然内建"。

Python 特性与模式

Python 特性          相关模式
动态类型            适配器更简单(无需接口)
一等函数            策略/命令可用函数实现
装饰器语法糖        装饰器模式天然支持
上下文管理器        模板方法/资源管理
迭代器协议         迭代器模式内建
元类               单例/工厂的进阶手段

示例:用函数实现策略模式

# 传统类实现
class Strategy:
    def execute(self, data): raise NotImplementedError

# Python 函数式:策略就是普通函数
def strategy_a(data):
    return sorted(data)

def strategy_b(data):
    return sorted(data, reverse=True)

def process(strategy, data):
    return strategy(data)

process(strategy_a, [3, 1, 2])   # [1, 2, 3]

学习建议

  • 先理解模式意图,再记结构
  • 用 Python 简化实现,不照搬 Java 样板
  • 避免过度设计:模式是为了解决问题

Python 工厂模式

Python 工厂模式

工厂模式将对象创建与使用分离,客户端无需关心具体类。

简单工厂(非 GoF 但常用)

class Dog:
    def speak(self): return "汪汪"

class Cat:
    def speak(self): return "喵喵"

class AnimalFactory:
    @staticmethod
    def create(animal_type):
        if animal_type == "dog":
            return Dog()
        elif animal_type == "cat":
            return Cat()
        raise ValueError("未知类型")

# 使用
animal = AnimalFactory.create("dog")
print(animal.speak())   # 汪汪

工厂方法模式

from abc import ABC, abstractmethod

class Creator(ABC):
    @abstractmethod
    def create(self): ...

    def do_something(self):
        obj = self.create()
        return obj.operate()

class DogCreator(Creator):
    def create(self):
        return Dog()

class CatCreator(Creator):
    def create(self):
        return Cat()

抽象工厂模式

class AnimalFactory(ABC):
    @abstractmethod
    def create_pet(self): ...

    @abstractmethod
    def create_wild(self): ...

class DogFactory(AnimalFactory):
    def create_pet(self): return Dog()
    def create_wild(self): return Wolf()

适用场景

对象创建逻辑复杂(参数化创建)
希望把创建代码集中管理
需要替换具体产品而不改客户端

Python 单例模式

Python 单例模式

单例确保一个类只有一个实例,常用于配置、连接池、日志等全局对象。

方式一:__new__ 实现

class Singleton:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance

    def __init__(self):
        self.value = 0

a = Singleton()
b = Singleton()
print(a is b)   # True

方式二:装饰器

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 Config:
    def __init__(self):
        self.retries = 3

c1 = Config()
c2 = Config()
print(c1 is c2)   # True

方式三:模块级单例(Pythonic)

# config.py
class Config:
    ...
config = Config()   # 模块天然单例

# 使用
from config import config

注意事项

1. 单例在多线程下要注意线程安全(加锁)
2. 单例增加全局状态,慎用,测试困难
3. 依赖注入常是更优替代方案

Python 建造者模式

Python 建造者模式

建造者模式将复杂对象的构建过程与表示分离,支持分步构建。

传统实现

class Computer:
    def __init__(self):
        self.cpu = None
        self.ram = None
        self.storage = None
        self.gpu = None

    def __str__(self):
        return f"CPU:{self.cpu} RAM:{self.ram} 存储:{self.storage} GPU:{self.gpu}"

class ComputerBuilder:
    def __init__(self):
        self.computer = Computer()

    def set_cpu(self, cpu):
        self.computer.cpu = cpu
        return self          # 支持链式

    def set_ram(self, ram):
        self.computer.ram = ram
        return self

    def set_storage(self, storage):
        self.computer.storage = storage
        return self

    def build(self):
        return self.computer

# 使用
pc = (ComputerBuilder()
      .set_cpu("i9")
      .set_ram("32GB")
      .set_storage("1TB SSD")
      .build())
print(pc)

链式调用(流畅接口)

builder = ComputerBuilder()
pc = (builder.set_cpu("i5")
            .set_ram("16GB")
            .build())

适用场景

对象有大量可选参数
构建步骤固定但实现可变化
希望避免构造器参数过多

Python 简化

# 参数少时直接用 dataclass 更简单
from dataclasses import dataclass

@dataclass
class Computer:
    cpu: str = "默认"
    ram: str = "8GB"
    storage: str = "256GB"

Python 原型模式

Python 原型模式

原型模式通过复制现有对象创建新对象,避免重新构造,利用 copy 模块实现。

浅拷贝与深拷贝

import copy

class Prototype:
    def __init__(self, name, data=None):
        self.name = name
        self.data = data if data else []

    def clone(self, shallow=True):
        if shallow:
            return copy.copy(self)      # 浅拷贝
        return copy.deepcopy(self)      # 深拷贝

original = Prototype("原始", [1, 2, 3])
shallow = original.clone()
deep = original.clone(shallow=False)

original.data.append(4)
print(shallow.data)   # [1, 2, 3, 4] 浅拷贝共享引用!
print(deep.data)      # [1, 2, 3]    深拷贝独立

原型注册表

class PrototypeRegistry:
    def __init__(self):
        self._prototypes = {}

    def register(self, name, prototype):
        self._prototypes[name] = prototype

    def clone(self, name, **kwargs):
        proto = self._prototypes[name]
        clone = copy.deepcopy(proto)
        clone.__dict__.update(kwargs)   # 覆盖属性
        return clone

适用场景

对象创建成本高(数据库查询、复杂计算)
对象有很多相似变体
避免大量工厂类

注意

默认 copy.copy 是浅拷贝,嵌套对象共享
自定义 __copy__/__deepcopy__ 控制拷贝行为

Python 适配器模式

Python 适配器模式

适配器让接口不兼容的类可以协作,Python 的动态特性让它实现非常自然。

类适配器

class Usb:
    def connect_usb(self):
        return "USB 连接"

class TypeC:
    def connect_typec(self):
        return "Type-C 连接"

# 适配器:把 TypeC 适配成 Usb 接口
class TypeCAdapter(Usb):
    def __init__(self, typec):
        self.typec = typec

    def connect_usb(self):
        return self.typec.connect_typec()

# 使用
adapter = TypeCAdapter(TypeC())
print(adapter.connect_usb())   # Type-C 连接

对象适配器

class Adapter:
    def __init__(self, obj, adapted_methods):
        self.obj = obj
        self.__dict__.update(adapted_methods)

def typec_to_usb(self):
    return self.obj.connect_typec()

adapter = Adapter(TypeC(), {"connect_usb": typec_to_usb})
print(adapter.connect_usb())

Python 特有:鸭子类型

# 只要方法签名一致,无需显式适配
def use_usb(device):
    return device.connect_usb()

use_usb(Usb())          # USB 连接
use_usb(TypeCAdapter(TypeC()))  # 适配后可用

适用场景

使用第三方库但接口不匹配
需要统一多个类的调用方式
无法修改现有类(无源码)

Python 装饰器模式

Python 装饰器模式

装饰器模式动态地为对象添加职责,Python 的 @decorator 语法天然支持。

函数装饰器

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"{func.__name__} 耗时 {time.time()-start:.3f}s")
        return result
    return wrapper

@timer
def slow_work():
    time.sleep(0.5)

slow_work()   # slow_work 耗时 0.500s

类装饰器(装饰器模式)

class LoggingDecorator:
    def __init__(self, component):
        self.component = component

    def operation(self):
        print("操作前:记录日志")
        result = self.component.operation()
        print("操作后:记录日志")
        return result

class BaseComponent:
    def operation(self):
        return "核心业务"

component = LoggingDecorator(BaseComponent())
print(component.operation())
# 操作前:记录日志
# 核心业务
# 操作后:记录日志

多层装饰

@timer
@cache
def compute(x):
    return x ** 2
# 执行顺序: timer(cache(compute))

适用场景

日志、计时、缓存、鉴权
在不修改原函数/类的情况下增强功能
需要动态组合多种职责

注意

用 functools.wraps 保留函数元信息
装饰器按定义顺序从下往上包装

Python 代理模式

Python 代理模式

代理模式为对象提供替身,控制对原对象的访问,常用于懒加载、访问控制、日志。

虚拟代理(懒加载)

class HeavyResource:
    def __init__(self):
        print("创建重型资源(耗时)")
        self.data = "大量数据"

    def read(self):
        return self.data

class LazyProxy:
    def __init__(self):
        self._resource = None

    def read(self):
        if self._resource is None:
            self._resource = HeavyResource()   # 延迟创建
        return self._resource.read()

proxy = LazyProxy()
print("代理已创建,尚未加载资源")
print(proxy.read())   # 此时才创建

保护代理(访问控制)

class BankAccount:
    def withdraw(self, amount):
        print(f"取款 {amount}")

class AccountProxy:
    def __init__(self, account, user_role):
        self.account = account
        self.user_role = user_role

    def withdraw(self, amount):
        if self.user_role != "admin":
            raise PermissionError("无权操作")
        self.account.withdraw(amount)

与装饰器模式区别

代理: 控制访问(替身),接口与目标一致
装饰器: 增强功能,可叠加多种职责

Python 简化

# 懒加载可用 property + __getattr__
class Proxy:
    def __getattr__(self, name):
        # 首次访问时初始化
        ...

Python 外观模式

Python 外观模式

外观模式为复杂子系统提供统一入口,简化调用。

实现

class CPU:
    def start(self): return "CPU 启动"
    def execute(self): return "CPU 执行"

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

class HardDrive:
    def read(self): return "硬盘读取"

class ComputerFacade:
    """外观:封装启动流程"""
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.hard = HardDrive()

    def start(self):
        steps = [
            self.cpu.start(),
            self.memory.load(),
            self.hard.read(),
            self.cpu.execute(),
        ]
        return " → ".join(steps)

# 客户端只面对一个简单接口
facade = ComputerFacade()
print(facade.start())

适用场景

子系统复杂,客户端只需要少量功能
希望为子系统提供简单默认入口
分层架构中为子系统提供门面

优点

客户端与子系统解耦
降低学习成本与出错概率
隐藏内部细节

注意

外观不应成为"万能类"——子系统仍可被直接使用
避免外观臃肿,保持单一职责

Python 桥接模式

Python 桥接模式

桥接模式将抽象与实现分离,使两者可以独立变化,避免继承爆炸。

问题场景

形状 × 颜色: 圆形红色、圆形蓝色、方形红色...
如果用继承: 4 个类(2×2),扩展时组合爆炸

桥接实现

class Color:
    def fill(self): raise NotImplementedError

class Red(Color):
    def fill(self): return "红色"

class Blue(Color):
    def fill(self): return "蓝色"

class Shape:
    def __init__(self, color):
        self.color = color      # 持有实现引用

    def draw(self): raise NotImplementedError

class Circle(Shape):
    def draw(self):
        return f"绘制圆形,填充{self.color.fill()}"

class Square(Shape):
    def draw(self):
        return f"绘制方形,填充{self.color.fill()}"

# 灵活组合:2 形状 × 2 颜色 = 4 种,只需 4 个类
red_circle = Circle(Red())
blue_square = Square(Blue())
print(red_circle.draw())
print(blue_square.draw())

适用场景

存在两个独立变化的维度
需要避免类爆炸
希望抽象与实现解耦

对比

适配器: 让已有接口协作
桥接: 设计阶段就分离抽象与实现

Python 组合模式

Python 组合模式

组合模式将对象组织成树形结构,让客户端对单个对象和组合对象一视同仁。

实现

class Component:
    def operation(self): raise NotImplementedError

class Leaf(Component):
    """叶子节点:文件"""
    def __init__(self, name):
        self.name = name

    def operation(self):
        return f"文件: {self.name}"

class Composite(Component):
    """组合节点:文件夹"""
    def __init__(self, name):
        self.name = name
        self.children = []

    def add(self, component):
        self.children.append(component)
        return self

    def operation(self):
        results = [child.operation() for child in self.children]
        return f"目录: {self.name} [{' | '.join(results)}]"

# 构建树
root = Composite("根目录")
doc = Composite("文档")
root.add(doc)
doc.add(Leaf("报告.pdf"))
doc.add(Leaf("笔记.md"))
root.add(Leaf("readme.txt"))

print(root.operation())
# 目录: 根目录 [目录: 文档 [文件: 报告.pdf | 文件: 笔记.md] | 文件: readme.txt]

适用场景

树形结构(文件系统、组织架构、UI 组件树)
客户端无需区分叶子与组合
希望对整体和部分统一操作

优点与注意

优点: 简化客户端,易扩展新类型
注意: 组合与叶子的接口可能过度泛化
Python 中列表字典天然可作组合结构

Python 享元模式

Python 享元模式

享元模式通过共享对象减少内存占用,适合大量相似对象的场景。

实现

class Character:
    """享元:共享的内部状态"""
    def __init__(self, char, font):
        self.char = char      # 内部状态(共享)
        self.font = font

    def display(self, position):
        # position 是外部状态(每次不同)
        return f"'{self.char}'({self.font}) 位于{position}"

class CharacterFactory:
    _pool = {}

    @classmethod
    def get(cls, char, font):
        key = (char, font)
        if key not in cls._pool:
            cls._pool[key] = Character(char, font)
        return cls._pool[key]

# 大量文本,字体有限的字符全部复用
f1 = CharacterFactory.get("A", "宋体")
f2 = CharacterFactory.get("A", "宋体")
f3 = CharacterFactory.get("A", "黑体")

print(f1 is f2)      # True 共享!
print(f1 is f3)      # False 字体不同

print(f1.display(1))
print(f1.display(2))  # 位置不同,显示不同

内部状态 vs 外部状态

内部状态: 共享不变(字符+字体)
外部状态: 随场景变化(位置),不存入享元

适用场景

大量相似对象(文本渲染、游戏粒子)
对象数量多导致内存压力大
对象可分为共享与独立部分

Python 观察者模式

Python 观察者模式

观察者模式定义一对多依赖:主题状态变化时自动通知所有观察者。

实现

class Subject:
    def __init__(self):
        self._observers = []
        self._state = None

    def attach(self, observer):
        self._observers.append(observer)

    def detach(self, observer):
        self._observers.remove(observer)

    def notify(self):
        for observer in self._observers:
            observer.update(self._state)

    def set_state(self, state):
        self._state = state
        self.notify()

class Observer:
    def update(self, state): raise NotImplementedError

class EmailNotifier(Observer):
    def update(self, state):
        print(f"邮件通知: 状态变为 {state}")

class SMSNotifier(Observer):
    def update(self, state):
        print(f"短信通知: 状态变为 {state}")

# 使用
subject = Subject()
subject.attach(EmailNotifier())
subject.attach(SMSNotifier())
subject.set_state("已发货")
# 邮件通知: 状态变为 已发货
# 短信通知: 状态变为 已发货

函数式观察者(Python 风格)

class Subject:
    def __init__(self):
        self._handlers = []
    def register(self, handler):
        self._handlers.append(handler)
    def notify(self, event):
        for h in self._handlers:
            h(event)

subject = Subject()
subject.register(lambda e: print(f"A 收到: {e}"))
subject.notify("事件!")

适用场景

事件驱动(UI 点击、消息推送)
发布-订阅模型
MVC 中 Model 通知 View

Python 策略模式

Python 策略模式

策略模式定义一组算法,让它们可互换,客户端动态选择。

类实现

class Strategy:
    def execute(self, data): raise NotImplementedError

class BubbleSort(Strategy):
    def execute(self, data):
        return sorted(data)

class QuickSort(Strategy):
    def execute(self, data):
        return sorted(data, reverse=True)   # 演示不同策略

class Context:
    def __init__(self, strategy):
        self.strategy = strategy

    def set_strategy(self, strategy):
        self.strategy = strategy

    def do_sort(self, data):
        return self.strategy.execute(data)

context = Context(BubbleSort())
print(context.do_sort([3, 1, 2]))
context.set_strategy(QuickSort())
print(context.do_sort([3, 1, 2]))

Python 函数式策略(推荐)

def sort_asc(data): return sorted(data)
def sort_desc(data): return sorted(data, reverse=True)

def process(sort_func, data):
    return sort_func(data)

process(sort_asc, [3, 1, 2])   # [1, 2, 3]
process(sort_desc, [3, 1, 2])  # [3, 2, 1]

适用场景

多个算法实现同一接口
需要运行时动态切换算法
避免大量 if-elif 分支

对比状态模式

策略: 客户端主动选择算法
状态: 状态自动驱动行为变化

Python 命令模式

Python 命令模式

命令模式把请求封装为对象,支持参数化、队列、撤销操作。

实现

class Light:
    def on(self): return "灯亮了"
    def off(self): return "灯灭了"

class Command:
    def execute(self): raise NotImplementedError
    def undo(self): raise NotImplementedError

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

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

class RemoteControl:
    def __init__(self):
        self.history = []

    def invoke(self, command):
        result = command.execute()
        self.history.append(command)
        return result

    def undo(self):
        if self.history:
            command = self.history.pop()
            return command.undo()
        return "无可撤销"

light = Light()
remote = RemoteControl()
print(remote.invoke(LightOnCommand(light)))   # 灯亮了
print(remote.undo())                           # 灯灭了

函数式命令(Python 风格)

def make_command(execute, undo=None):
    return {"execute": execute, "undo": undo}

cmd = make_command(lambda: "执行", lambda: "撤销")
cmd["execute"]()

适用场景

撤销/重做功能
任务队列、宏命令
GUI 按钮与菜单操作

Python 模板方法模式

Python 模板方法模式

模板方法在父类定义算法骨架,将可变步骤延迟到子类实现。

实现

from abc import ABC, abstractmethod

class DataMiner(ABC):
    """模板方法定义处理流程"""
    def mine(self):
        data = self.load_data()
        processed = self.process(data)
        self.output(processed)

    def load_data(self):
        return "原始数据"

    @abstractmethod
    def process(self, data):
        pass

    def output(self, data):
        print(f"输出: {data}")

class CSVDataMiner(DataMiner):
    def process(self, data):
        return f"解析CSV: {data}"

class JSONDataMiner(DataMiner):
    def process(self, data):
        return f"解析JSON: {data}"

CSVDataMiner().mine()    # 输出: 解析CSV: 原始数据
JSONDataMiner().mine()   # 输出: 解析JSON: 原始数据

钩子方法

class DataMiner(ABC):
    def mine(self):
        data = self.load_data()
        if self.need_process():       # 钩子
            data = self.process(data)
        self.output(data)

    def need_process(self):           # 默认钩子
        return True

适用场景

多个流程结构相同、细节不同
框架设计(框架定骨架,用户实现钩子)
防止重复代码

对比策略模式

模板方法: 继承,骨架在父类
策略: 组合,算法可整体替换

Python 迭代器模式

Python 迭代器模式

迭代器模式提供顺序访问集合元素的方式,Python 的迭代器协议天然内建。

Python 迭代器协议

iterable: 有 __iter__() 返回迭代器
iterator: 有 __next__() 返回下一个或抛 StopIteration

自定义迭代器

class CountDown:
    def __init__(self, start):
        self.start = start

    def __iter__(self):
        return self            # 自身就是迭代器

    def __next__(self):
        if self.start <= 0:
            raise StopIteration
        self.start -= 1
        return self.start + 1

for n in CountDown(3):
    print(n)   # 3 2 1

生成器(Python 风格迭代器)

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(5):
    print(num)   # 0 1 1 2 3

itertools 常用工具

import itertools
itertools.chain([1,2], [3,4])      # 拼接迭代
itertools.islice(iter, 10)         # 切片迭代
itertools.zip_longest(a, b)        # 长zip
itertools.product([1,2], [3,4])    # 笛卡尔积

适用场景

需要统一遍历不同集合结构
大数据流式处理(惰性)
Python 中实现 __iter__/__next__ 或生成器即可

Python 责任链模式

Python 责任链模式

责任链将请求沿处理器链传递,每个处理器决定处理还是转交下一个。

实现

class Handler:
    def __init__(self):
        self.next_handler = None

    def set_next(self, handler):
        self.next_handler = handler
        return handler          # 支持链式

    def handle(self, request):
        if self.next_handler:
            return self.next_handler.handle(request)
        return None

class Level1Support(Handler):
    def handle(self, request):
        if request <= 10:
            return f"L1 处理: {request}"
        return super().handle(request)

class Level2Support(Handler):
    def handle(self, request):
        if request <= 100:
            return f"L2 处理: {request}"
        return super().handle(request)

class Level3Support(Handler):
    def handle(self, request):
        return f"L3 处理: {request}"

# 构建链: L1 → L2 → L3
chain = Level1Support()
chain.set_next(Level2Support()).set_next(Level3Support())

print(chain.handle(5))     # L1 处理: 5
print(chain.handle(50))    # L2 处理: 50
print(chain.handle(500))   # L3 处理: 500

Python 简化(列表+循环)

handlers = [Level1Support(), Level2Support(), Level3Support()]
def handle(request):
    for h in handlers:
        result = h.handle(request)
        if result:
            return result

# 或优雅降级: try/except 链

适用场景

审批流、日志级别过滤
请求处理顺序不确定或动态调整
避免大量 if-elif

Python 状态模式

Python 状态模式

状态模式让对象在内部状态变化时改变行为,消除大量条件判断。

实现

class State:
    def handle(self, context): raise NotImplementedError

class DraftState(State):
    def handle(self, context):
        print("草稿状态: 审核中...")
        context.state = ReviewState()

class ReviewState(State):
    def handle(self, context):
        print("审核状态: 已通过...")
        context.state = PublishedState()

class PublishedState(State):
    def handle(self, context):
        print("已发布状态: 不可再变更")

class Document:
    def __init__(self):
        self.state = DraftState()

    def next_step(self):
        self.state.handle(self)

# 状态流转: 草稿 → 审核 → 发布
doc = Document()
doc.next_step()   # 草稿状态: 审核中...
doc.next_step()   # 审核状态: 已通过...
doc.next_step()   # 已发布状态: 不可再变更

适用场景

对象行为随状态变化(订单、审批、播放器)
有大量 if-state 分支
状态转换规则复杂

对比策略模式

状态: 状态自动切换,行为随状态变化
策略: 客户端主动选择算法,状态不变

Python 访问者模式

Python 访问者模式

访问者模式在不修改类的前提下,为对象结构增加新操作。

实现

class Node:
    def accept(self, visitor):
        raise NotImplementedError

class File(Node):
    def __init__(self, name, size):
        self.name = name
        self.size = size

    def accept(self, visitor):
        return visitor.visit_file(self)

class Directory(Node):
    def __init__(self, name):
        self.name = name
        self.children = []

    def add(self, node):
        self.children.append(node)

    def accept(self, visitor):
        return visitor.visit_directory(self)

class SizeVisitor:
    """统计总大小"""
    def visit_file(self, file):
        return file.size

    def visit_directory(self, directory):
        return sum(c.accept(self) for c in directory.children)

class CountVisitor:
    """统计文件数量"""
    def visit_file(self, file):
        return 1

    def visit_directory(self, directory):
        return sum(c.accept(self) for c in directory.children)

# 使用
root = Directory("root")
root.add(File("a.txt", 10))
sub = Directory("sub")
sub.add(File("b.log", 20))
root.add(sub)

print(SizeVisitor().visit_directory(root))    # 30
print(CountVisitor().visit_directory(root))   # 2
# 新增操作只需加新 Visitor,不用改 Node 类

适用场景

对象结构稳定但操作频繁变化
需要对结构执行多种不相关操作
避免在每个类加新方法

注意

增加新节点类型需要修改所有访问者(违反开闭原则)
Python 可用 singledispatch 简化

Python 中介者模式

Python 中介者模式

中介者封装对象间的交互,减少对象之间的直接耦合。

实现

class ChatRoom:
    """中介者"""
    def __init__(self):
        self.users = []

    def add_user(self, user):
        self.users.append(user)

    def send(self, message, sender):
        for user in self.users:
            if user != sender:
                user.receive(message, sender.name)

class User:
    def __init__(self, name, room):
        self.name = name
        self.room = room
        room.add_user(self)

    def send(self, message):
        self.room.send(message, self)

    def receive(self, message, sender):
        print(f"{self.name} 收到来自 {sender} 的消息: {message}")

# 使用:用户之间不直接引用,只通过中介者
room = ChatRoom()
alice = User("Alice", room)
bob = User("Bob", room)
alice.send("大家好!")   # Bob 收到

适用场景

对象之间交互复杂(UI 组件、聊天室、航班系统)
希望解耦网状依赖
交互逻辑集中管理

优缺点

优点: 减少耦合,交互集中
缺点: 中介者可能变得庞大(上帝对象)

Python 备忘录模式

Python 备忘录模式

备忘录模式保存对象状态以便恢复,实现撤销功能。

实现

class Memento:
    """备忘录:不可变状态快照"""
    def __init__(self, state):
        self._state = state

    def get_state(self):
        return self._state

class Editor:
    def __init__(self):
        self.content = ""

    def write(self, text):
        self.content += text

    def save(self):
        return Memento(self.content)

    def restore(self, memento):
        self.content = memento.get_state()

class History:
    def __init__(self):
        self.snapshots = []

    def push(self, memento):
        self.snapshots.append(memento)

    def pop(self):
        return self.snapshots.pop()

# 使用
editor = Editor()
history = History()

editor.write("你好")
history.push(editor.save())

editor.write("世界")
history.push(editor.save())

editor.write("(误操作)")
print(editor.content)          # 你好世界(误操作)

editor.restore(history.pop())
print(editor.content)          # 你好世界
editor.restore(history.pop())
print(editor.content)          # 你好

适用场景

撤销/重做(编辑器、游戏存档)
需要保存状态历史
状态快照需要与对象解耦

注意

快照量大时内存开销大
Python 可用 copy.deepcopy 简化

Python 解释器模式

Python 解释器模式

解释器模式为语言定义文法,并解释执行句子,用于实现 DSL 和表达式求值。

实现(简单数学表达式)

class Expression:
    def interpret(self): raise NotImplementedError

class Number(Expression):
    def __init__(self, value):
        self.value = value

    def interpret(self):
        return self.value

class Add(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self):
        return self.left.interpret() + self.right.interpret()

class Subtract(Expression):
    def __init__(self, left, right):
        self.left = left
        self.right = right

    def interpret(self):
        return self.left.interpret() - self.right.interpret()

# 解析 (10 + 20) - 5 为语法树
expr = Subtract(Add(Number(10), Number(20)), Number(5))
print(expr.interpret())   # 25

Python 简化:直接求值/ast

# 用 Python 语法树模块解析
import ast

tree = ast.parse("10 + 20 - 5", mode="eval")
print(ast.literal_eval("10 + 20 - 5"))   # 简单字面量

# eval 注意安全风险,生产勿用裸 eval

适用场景

实现 DSL(规则引擎、查询语言)
表达式求值(计算器、公式)
语法分析器

注意

语法复杂时解释器类爆炸,考虑用现成解析库
Python 有 pyparsing、PLY、lark 等解析工具
第 1 / 24 节