设计模式实战笔记:从创建型到行为型

前言:设计模式是经验的结晶

设计模式不是炫技,是前人踩坑后的经验总结。用对模式让代码更易维护、扩展、测试;用错模式反而增加复杂度。

设计模式三大类:

  • 创建型:对象创建(5 种)
  • 结构型:对象组合(7 种)
  • 行为型:对象交互(11 种)

一、创建型模式

1.1 单例模式(Singleton)

# 线程安全的单例
class Database:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:  # 双重检查
                    cls._instance = super().__new__(cls)
        return cls._instance

# Python 装饰器实现
def singleton(cls):
    instances = {}
    @wraps(cls)
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class Config:
    pass

适用场景: 数据库连接、配置管理、日志器 坑: 全局状态,测试难。依赖注入替代。

1.2 工厂模式(Factory)

# 简单工厂
class AnimalFactory:
    @staticmethod
    def create(animal_type):
        if animal_type == 'dog':
            return Dog()
        elif animal_type == 'cat':
            return Cat()
        raise ValueError(f"Unknown animal: {animal_type}")

# 工厂方法
class AnimalFactory(ABC):
    @abstractmethod
    def create(self) -> Animal:
        pass

class DogFactory(AnimalFactory):
    def create(self) -> Animal:
        return Dog()

# 抽象工厂
class GUIFactory(ABC):
    @abstractmethod
    def create_button(self): pass
    @abstractmethod
    def create_input(self): pass

class MacGUIFactory(GUIFactory):
    def create_button(self): return MacButton()
    def create_input(self): return MacInput()

1.3 建造者模式(Builder)

class Pizza:
    def __init__(self):
        self.size = None
        self.cheese = False
        self.pepperoni = False
        self.mushrooms = False

class PizzaBuilder:
    def __init__(self):
        self.pizza = Pizza()

    def set_size(self, size):
        self.pizza.size = size
        return self

    def add_cheese(self):
        self.pizza.cheese = True
        return self

    def add_pepperoni(self):
        self.pizza.pepperoni = True
        return self

    def build(self):
        return self.pizza

# 使用
pizza = (PizzaBuilder()
    .set_size('large')
    .add_cheese()
    .add_pepperoni()
    .build())

1.4 原型模式(Prototype)

import copy

class Document:
    def __init__(self, content):
        self.content = content

    def clone(self):
        return copy.deepcopy(self)

# 使用
template = Document("Template content")
doc1 = template.clone()
doc1.content = "Custom content"

二、结构型模式

2.1 适配器模式(Adapter)

# 旧接口
class OldPrinter:
    def print_old(self, text):
        print(f"OLD: {text}")

# 新接口
class Printer(ABC):
    @abstractmethod
    def print(self, text): pass

# 适配器
class PrinterAdapter(Printer):
    def __init__(self, old_printer):
        self.old_printer = old_printer

    def print(self, text):
        self.old_printer.print_old(text)

# 使用
adapter = PrinterAdapter(OldPrinter())
adapter.print("Hello")  # 输出: OLD: Hello

2.2 装饰器模式(Decorator)

# 咖啡基础类
class Coffee:
    def cost(self): return 5
    def description(self): return "Coffee"

# 装饰器基类
class CoffeeDecorator:
    def __init__(self, coffee):
        self.coffee = coffee

    def cost(self): return self.coffee.cost()
    def description(self): return self.coffee.description()

# 具体装饰器
class Milk(CoffeeDecorator):
    def cost(self): return self.coffee.cost() + 2
    def description(self): return self.coffee.description() + ", Milk"

class Sugar(CoffeeDecorator):
    def cost(self): return self.coffee.cost() + 1
    def description(self): return self.coffee.description() + ", Sugar"

# 使用
coffee = Sugar(Milk(Coffee()))
print(coffee.description())  # Coffee, Milk, Sugar
print(coffee.cost())         # 8

2.3 代理模式(Proxy)

# 虚拟代理:延迟加载
class ImageProxy:
    def __init__(self, filename):
        self.filename = filename
        self.image = None

    def display(self):
        if self.image is None:
            self.image = Image(self.filename)  # 第一次调用才加载
        self.image.display()

# 缓存代理
class CacheProxy:
    def __init__(self, service):
        self.service = service
        self.cache = {}

    def get(self, key):
        if key not in self.cache:
            self.cache[key] = self.service.get(key)
        return self.cache[key]

2.4 外观模式(Facade)

class ComputerFacade:
    def __init__(self):
        self.cpu = CPU()
        self.memory = Memory()
        self.disk = Disk()

    def start(self):
        self.cpu.freeze()
        self.memory.load()
        self.disk.read()
        self.cpu.execute()

    def shutdown(self):
        self.cpu.freeze()
        self.disk.flush()
        self.memory.unload()

# 使用:客户端不需要知道 CPU/Memory/Disk 怎么协作
computer = ComputerFacade()
computer.start()

三、行为型模式

3.1 观察者模式(Observer)

from typing import List, Callable

class EventEmitter:
    def __init__(self):
        self._listeners = {}

    def on(self, event: str, callback: Callable):
        if event not in self._listeners:
            self._listeners[event] = []
        self._listeners[event].append(callback)

    def emit(self, event: str, *args, **kwargs):
        for callback in self._listeners.get(event, []):
            callback(*args, **kwargs)

# 使用
emitter = EventEmitter()
emitter.on('user_created', lambda user: send_email(user))
emitter.on('user_created', lambda user: update_analytics(user))

emitter.emit('user_created', {'id': 1, 'name': 'Alice'})

3.2 策略模式(Strategy)

from typing import Protocol

class PaymentStrategy(Protocol):
    def pay(self, amount: float) -> bool: ...

class CreditCardPayment:
    def pay(self, amount): return process_credit_card(amount)

class AlipayPayment:
    def pay(self, amount): return process_alipay(amount)

class PaymentContext:
    def __init__(self, strategy: PaymentStrategy):
        self.strategy = strategy

    def execute_payment(self, amount):
        return self.strategy.pay(amount)

# 使用
payment = PaymentContext(AlipayPayment())
payment.execute_payment(100)

3.3 命令模式(Command)

class Command:
    def execute(self): pass
    def undo(self): pass

class AddTextCommand(Command):
    def __init__(self, editor, text):
        self.editor = editor
        self.text = text

    def execute(self):
        self.editor.text += self.text

    def undo(self):
        self.editor.text = self.editor.text[:-len(self.text)]

class Editor:
    def __init__(self):
        self.text = ""
        self.history = []

    def execute(self, command):
        command.execute()
        self.history.append(command)

    def undo(self):
        if self.history:
            self.history.pop().undo()

3.4 责任链模式(Chain of Responsibility)

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 AuthHandler(Handler):
    def handle(self, request):
        if not request.get('token'):
            return "Unauthorized"
        return super().handle(request)

class RateLimitHandler(Handler):
    def handle(self, request):
        if is_rate_limited(request):
            return "Rate limited"
        return super().handle(request)

class BusinessHandler(Handler):
    def handle(self, request):
        return process_business(request)

# 构建链
auth = AuthHandler()
rate_limit = RateLimitHandler()
business = BusinessHandler()

auth.set_next(rate_limit).set_next(business)
result = auth.handle({'token': 'abc'})

3.5 状态模式(State)

class OrderState:
    def next(self, order): pass
    def cancel(self, order): pass

class CreatedState(OrderState):
    def next(self, order):
        order.state = PaidState()

    def cancel(self, order):
        order.state = CancelledState()

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

    def cancel(self, order):
        # 退款逻辑
        order.state = CancelledState()

class Order:
    def __init__(self):
        self.state = CreatedState()

    def pay(self):
        self.state.next(self)

    def cancel(self):
        self.state.cancel(self)

四、游戏设计模式:组件模式

4.1 继承 vs 组件

# 传统继承(深层继承链)
class GameObject:
    pass

class Character(GameObject):
    pass

class Player(Character):
    pass  # 想加物理?想加渲染?继承链越来越深

# 组件模式(扁平组合)
class Component:
    def update(self, dt): pass

class PhysicsComponent(Component):
    def __init__(self):
        self.velocity = Vector2(0, 0)
        self.mass = 1.0

    def update(self, dt, entity):
        entity.position += self.velocity * dt

class RenderComponent(Component):
    def __init__(self, sprite):
        self.sprite = sprite

    def update(self, dt, entity):
        draw_sprite(self.sprite, entity.position)

class InputComponent(Component):
    def update(self, dt, entity):
        if is_key_pressed('left'):
            entity.physics.velocity.x = -100

class Entity:
    def __init__(self):
        self.position = Vector2(0, 0)
        self.components = {}

    def add_component(self, name, component):
        self.components[name] = component

    def get_component(self, name):
        return self.components.get(name)

    def update(self, dt):
        for component in self.components.values():
            component.update(dt, self)

# 创建玩家
player = Entity()
player.add_component('physics', PhysicsComponent())
player.add_component('render', RenderComponent('player.png'))
player.add_component('input', InputComponent())

五、SOLID 原则

原则说明示例
Single Responsibility单一职责一个类只做一件事
Open/Closed开闭原则对扩展开放,对修改关闭
Liskov Substitution里氏替换子类可以替换父类
Interface Segregation接口隔离小接口优于大接口
Dependency Inversion依赖倒置依赖抽象不依赖具体

六、踩坑总结

坑一:过度设计

简单 CRUD 也要套一堆模式。模式是为了解决问题,不是为了用而用。

坑二:选错模式

观察者解耦了通知,但调试困难。不是所有事件通知都适合观察者。

坑三:单例滥用

全局状态难测试。优先依赖注入。

七、写在最后

几条核心原则:

  1. 模式是工具,不是目的
  2. 简单优先:能 if-else 解决的别用策略模式
  3. 针对变化使用模式:如果不会变化,别提前设计
  4. 组合优于继承
  5. SOLID 是基础

设计模式的核心价值不是让你写出更"高级"的代码,而是让代码更容易理解和维护


本文整合了 3 篇设计模式相关文章,涵盖创建型、结构型、行为型模式以及游戏组件模式、SOLID 原则等核心内容。

版权声明: 本文首发于 指尖魔法屋-设计模式实战笔记:从创建型到行为型https://blog.thinkmoon.cn/post/design-patterns-comprehensive-guide/) 转载或引用必须申明原指尖魔法屋来源及源地址!