设计模式实战笔记:从创建型到行为型
前言:设计模式是经验的结晶
设计模式不是炫技,是前人踩坑后的经验总结。用对模式让代码更易维护、扩展、测试;用错模式反而增加复杂度。
设计模式三大类:
- 创建型:对象创建(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 也要套一堆模式。模式是为了解决问题,不是为了用而用。
坑二:选错模式
观察者解耦了通知,但调试困难。不是所有事件通知都适合观察者。
坑三:单例滥用
全局状态难测试。优先依赖注入。
七、写在最后
几条核心原则:
- 模式是工具,不是目的
- 简单优先:能 if-else 解决的别用策略模式
- 针对变化使用模式:如果不会变化,别提前设计
- 组合优于继承
- SOLID 是基础
设计模式的核心价值不是让你写出更"高级"的代码,而是让代码更容易理解和维护。
本文整合了 3 篇设计模式相关文章,涵盖创建型、结构型、行为型模式以及游戏组件模式、SOLID 原则等核心内容。
版权声明: 本文首发于 指尖魔法屋-设计模式实战笔记:从创建型到行为型(https://blog.thinkmoon.cn/post/design-patterns-comprehensive-guide/) 转载或引用必须申明原指尖魔法屋来源及源地址!
评论
使用 GitHub 账号登录后即可留言,支持 Markdown。