设计模式之行为型设计模式详解
·
行为型模式关注对象之间的通信和职责分配,定义了对象间的交互方式和算法的封装。
目录
- 责任链模式 (Chain of Responsibility)
- 命令模式 (Command)
- 解释器模式 (Interpreter)
- 迭代器模式 (Iterator)
- 中介者模式 (Mediator)
- 备忘录模式 (Memento)
- 观察者模式 (Observer)
- 状态模式 (State)
- 策略模式 (Strategy)
- 模板方法模式 (Template Method)
- 访问者模式 (Visitor)
1. 责任链模式 (Chain of Responsibility)
定义
使多个对象都有机会处理请求,从而避免请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递请求,直到有一个对象处理它为止。
生活类比
- 公司报销审批:员工提交报销单,先给组长审批,额度超限则转给经理,再超限转给总监
- 技术支持热线:一级客服解决不了转二级,二级解决不了转专家
Python 实现
from abc import ABC, abstractmethod
from typing import Optional
class Handler(ABC):
def __init__(self):
self._successor: Optional[Handler] = None
def set_successor(self, successor: 'Handler'):
self._successor = successor
@abstractmethod
def handle_request(self, amount: float):
pass
class TeamLeader(Handler):
def handle_request(self, amount: float):
if amount <= 1000:
print(f"组长批准了 {amount} 元的报销")
elif self._successor:
print(f"组长无法批准 {amount} 元,转交给上级")
self._successor.handle_request(amount)
class Manager(Handler):
def handle_request(self, amount: float):
if amount <= 5000:
print(f"经理批准了 {amount} 元的报销")
elif self._successor:
print(f"经理无法批准 {amount} 元,转交给上级")
self._successor.handle_request(amount)
class Director(Handler):
def handle_request(self, amount: float):
if amount <= 10000:
print(f"总监批准了 {amount} 元的报销")
else:
print(f"总监:{amount} 元超出权限,需要董事会决议")
if __name__ == "__main__":
leader = TeamLeader()
manager = Manager()
director = Director()
leader.set_successor(manager)
manager.set_successor(director)
expenses = [800, 3000, 7000, 15000]
for expense in expenses:
print(f"\n申请报销: {expense} 元")
leader.handle_request(expense)
2. 命令模式 (Command)
定义
将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。
生活类比
- 餐厅点餐:服务员(调用者)记录订单(命令),厨师(接收者)执行
- 遥控器:按钮(命令)控制各种家电(接收者),可以记录、撤销操作
Python 实现
from abc import ABC, abstractmethod
from typing import List
class Command(ABC):
@abstractmethod
def execute(self):
pass
@abstractmethod
def undo(self):
pass
class Light:
def __init__(self, location: str):
self.location = location
self.is_on = False
def on(self):
self.is_on = True
print(f"{self.location} 灯已打开")
def off(self):
self.is_on = False
print(f"{self.location} 灯已关闭")
class LightOnCommand(Command):
def __init__(self, light: Light):
self.light = light
self.previous_state = False
def execute(self):
self.previous_state = self.light.is_on
self.light.on()
def undo(self):
if not self.previous_state:
self.light.off()
class RemoteControl:
def __init__(self):
self.commands: dict = {}
self.history: List[Command] = []
def set_command(self, slot: str, command: Command):
self.commands[slot] = command
def press_button(self, slot: str):
if slot in self.commands:
command = self.commands[slot]
command.execute()
self.history.append(command)
def press_undo(self):
if self.history:
command = self.history.pop()
print("\n撤销上一个操作:")
command.undo()
if __name__ == "__main__":
remote = RemoteControl()
living_room_light = Light("客厅")
remote.set_command("A", LightOnCommand(living_room_light))
remote.press_button("A")
remote.press_undo()
3. 解释器模式 (Interpreter)
定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
生活类比
- 翻译软件:将一种语言的句子解析并转换成另一种语言
- 计算器:解析数学表达式并计算结果
- 正则表达式:定义匹配规则并解释执行
Python 实现
from abc import ABC, abstractmethod
from typing import Dict
class Context:
def __init__(self):
self.variables: Dict[str, int] = {}
def set_variable(self, name: str, value: int):
self.variables[name] = value
def get_variable(self, name: str) -> int:
return self.variables.get(name, 0)
class Expression(ABC):
@abstractmethod
def interpret(self, context: Context) -> int:
pass
class NumberExpression(Expression):
def __init__(self, value: int):
self.value = value
def interpret(self, context: Context) -> int:
return self.value
class VariableExpression(Expression):
def __init__(self, name: str):
self.name = name
def interpret(self, context: Context) -> int:
return context.get_variable(self.name)
class AddExpression(Expression):
def __init__(self, left: Expression, right: Expression):
self.left = left
self.right = right
def interpret(self, context: Context) -> int:
return self.left.interpret(context) + self.right.interpret(context)
if __name__ == "__main__":
context = Context()
context.set_variable("x", 10)
context.set_variable("y", 5)
# (x + y) * 2
expression = AddExpression(
VariableExpression("x"),
VariableExpression("y")
)
result = expression.interpret(context)
print(f"x + y = {result}")
4. 迭代器模式 (Iterator)
定义
提供一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部表示。
生活类比
- 电视遥控器换台:按上下键遍历频道,不需要知道电视台内部如何存储
- 翻书:一页一页翻看,不需要知道书是如何装订的
Python 实现
from abc import ABC, abstractmethod
from typing import List, Any
class Iterator(ABC):
@abstractmethod
def has_next(self) -> bool:
pass
@abstractmethod
def next(self) -> Any:
pass
class Book:
def __init__(self, title: str):
self.title = title
class BookShelf:
def __init__(self):
self._books: List[Book] = []
def add_book(self, book: Book):
self._books.append(book)
def create_iterator(self):
return BookShelfIterator(self)
def get_book_at(self, index: int) -> Book:
return self._books[index]
def get_length(self) -> int:
return len(self._books)
class BookShelfIterator(Iterator):
def __init__(self, book_shelf: BookShelf):
self._book_shelf = book_shelf
self._index = 0
def has_next(self) -> bool:
return self._index < self._book_shelf.get_length()
def next(self) -> Book:
book = self._book_shelf.get_book_at(self._index)
self._index += 1
return book
if __name__ == "__main__":
book_shelf = BookShelf()
book_shelf.add_book(Book("设计模式"))
book_shelf.add_book(Book("Clean Code"))
iterator = book_shelf.create_iterator()
while iterator.has_next():
book = iterator.next()
print(f"Book: {book.title}")
5. 中介者模式 (Mediator)
定义
用一个中介对象来封装一系列的对象交互。中介者使各对象不需要显式地相互引用,从而使其耦合松散。
生活类比
- 机场塔台:飞机之间不直接通信,而是通过塔台协调起降
- 聊天室:用户通过聊天室服务器转发消息,而不是直接发送给每个人
Python 实现
from abc import ABC, abstractmethod
from typing import List
class Mediator(ABC):
@abstractmethod
def send_message(self, message: str, colleague: 'Colleague'):
pass
class Colleague(ABC):
def __init__(self, name: str, mediator: Mediator):
self.name = name
self._mediator = mediator
def send(self, message: str):
self._mediator.send_message(message, self)
@abstractmethod
def receive_message(self, message: str):
pass
class ChatRoom(Mediator):
def __init__(self):
self._participants: List[Colleague] = []
def register(self, colleague: Colleague):
self._participants.append(colleague)
def send_message(self, message: str, sender: Colleague):
for participant in self._participants:
if participant != sender:
participant.receive_message(f"[{sender.name}]: {message}")
class User(Colleague):
def receive_message(self, message: str):
print(f"{self.name} 收到: {message}")
if __name__ == "__main__":
chat_room = ChatRoom()
alice = User("Alice", chat_room)
bob = User("Bob", chat_room)
chat_room.register(alice)
chat_room.register(bob)
alice.send("Hello!")
6. 备忘录模式 (Memento)
定义
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。
生活类比
- 游戏存档:保存游戏进度,可以随时读档回到之前的状态
- Ctrl+Z撤销:编辑器保存历史状态,支持撤销操作
Python 实现
from abc import ABC, abstractmethod
from typing import List
from datetime import datetime
class Memento:
def __init__(self, content: str, cursor_position: int):
self._content = content
self._cursor_position = cursor_position
self._timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
def get_content(self) -> str:
return self._content
def get_timestamp(self) -> str:
return self._timestamp
class TextEditor:
def __init__(self):
self._content = ""
self._cursor_position = 0
def type(self, text: str):
self._content += text
print(f"输入: '{text}' -> '{self._content}'")
def create_memento(self) -> Memento:
return Memento(self._content, self._cursor_position)
def restore_memento(self, memento: Memento):
self._content = memento.get_content()
print(f"恢复: '{self._content}'")
class History:
def __init__(self):
self._history: List[Memento] = []
def backup(self, memento: Memento):
self._history.append(memento)
def undo(self) -> Memento:
if len(self._history) > 1:
self._history.pop()
return self._history[-1]
return None
if __name__ == "__main__":
editor = TextEditor()
history = History()
history.backup(editor.create_memento())
editor.type("Hello")
history.backup(editor.create_memento())
editor.type(" World")
memento = history.undo()
if memento:
editor.restore_memento(memento)
7. 观察者模式 (Observer)
定义
定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。
生活类比
- 微信公众号:订阅者收到新文章推送
- 天气预报:多个显示面板同步更新天气数据
Python 实现
from abc import ABC, abstractmethod
from typing import List
class Observer(ABC):
@abstractmethod
def update(self, temperature: float, humidity: float):
pass
class Subject(ABC):
@abstractmethod
def attach(self, observer: Observer):
pass
@abstractmethod
def notify(self):
pass
class WeatherStation(Subject):
def __init__(self):
self._observers: List[Observer] = []
self._temperature = 0.0
def attach(self, observer: Observer):
self._observers.append(observer)
def notify(self):
for observer in self._observers:
observer.update(self._temperature, 0.0)
def set_temperature(self, temperature: float):
self._temperature = temperature
self.notify()
class PhoneDisplay(Observer):
def update(self, temperature: float, humidity: float):
print(f"Phone: Temperature is {temperature}")
if __name__ == "__main__":
weather = WeatherStation()
phone = PhoneDisplay()
weather.attach(phone)
weather.set_temperature(25.0)
8. 状态模式 (State)
定义
允许对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
生活类比
- 电梯:有停止、运行、开门、关门等状态,每种状态下行为不同
- 红绿灯:红灯停、绿灯行、黄灯等待
Python 实现
from abc import ABC, abstractmethod
class State(ABC):
@abstractmethod
def handle(self, context: 'TrafficLight'):
pass
class RedState(State):
def handle(self, context: 'TrafficLight'):
print("Red: Stop!")
context.set_state(GreenState())
class GreenState(State):
def handle(self, context: 'TrafficLight'):
print("Green: Go!")
context.set_state(YellowState())
class YellowState(State):
def handle(self, context: 'TrafficLight'):
print("Yellow: Prepare to stop")
context.set_state(RedState())
class TrafficLight:
def __init__(self):
self._state = RedState()
def set_state(self, state: State):
self._state = state
def change(self):
self._state.handle(self)
if __name__ == "__main__":
light = TrafficLight()
for _ in range(6):
light.change()
9. 策略模式 (Strategy)
定义
定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。本模式使得算法可独立于使用它的客户而变化。
生活类比
- 导航软件:可以选择最快路线、最短路线、避开高速等策略
- 支付方式:支付宝、微信、信用卡等不同支付策略
Python 实现
from abc import ABC, abstractmethod
from typing import List
class SortStrategy(ABC):
@abstractmethod
def sort(self, data: List[int]) -> List[int]:
pass
class BubbleSortStrategy(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
arr = data.copy()
n = len(arr)
for i in range(n):
for j in range(0, n - i - 1):
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
return arr
class QuickSortStrategy(SortStrategy):
def sort(self, data: List[int]) -> List[int]:
if len(data) <= 1:
return data
pivot = data[len(data) // 2]
left = [x for x in data if x < pivot]
middle = [x for x in data if x == pivot]
right = [x for x in data if x > pivot]
return self.sort(left) + middle + self.sort(right)
class Sorter:
def __init__(self, strategy: SortStrategy = None):
self._strategy = strategy or QuickSortStrategy()
def set_strategy(self, strategy: SortStrategy):
self._strategy = strategy
def sort(self, data: List[int]) -> List[int]:
return self._strategy.sort(data)
if __name__ == "__main__":
data = [64, 34, 25, 12, 22, 11, 90]
sorter = Sorter()
sorter.set_strategy(BubbleSortStrategy())
print(f"Bubble: {sorter.sort(data)}")
sorter.set_strategy(QuickSortStrategy())
print(f"Quick: {sorter.sort(data)}")
10. 模板方法模式 (Template Method)
定义
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
生活类比
- 冲泡饮料:泡茶和泡咖啡的步骤类似(烧水、冲泡、倒入杯中、加调料),但具体实现不同
- 建造房屋:建造流程固定(打地基、建墙体、盖屋顶),但材料不同
Python 实现
from abc import ABC, abstractmethod
class CaffeineBeverage(ABC):
def prepare_recipe(self):
self.boil_water()
self.brew()
self.pour_in_cup()
self.add_condiments()
def boil_water(self):
print("Boiling water")
def pour_in_cup(self):
print("Pouring into cup")
@abstractmethod
def brew(self):
pass
@abstractmethod
def add_condiments(self):
pass
class Tea(CaffeineBeverage):
def brew(self):
print("Steeping the tea")
def add_condiments(self):
print("Adding lemon")
class Coffee(CaffeineBeverage):
def brew(self):
print("Dripping coffee through filter")
def add_condiments(self):
print("Adding sugar and milk")
if __name__ == "__main__":
tea = Tea()
tea.prepare_recipe()
print()
coffee = Coffee()
coffee.prepare_recipe()
11. 访问者模式 (Visitor)
定义
表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。
生活类比
- 医院体检:病人(元素)接受不同科室医生(访问者)的检查
- 税务申报:不同类型的收入接受不同的税务计算规则
Python 实现
from abc import ABC, abstractmethod
from typing import List
class Visitor(ABC):
@abstractmethod
def visit_employee(self, employee: 'Employee'):
pass
@abstractmethod
def visit_department(self, department: 'Department'):
pass
class OrganizationElement(ABC):
@abstractmethod
def accept(self, visitor: Visitor):
pass
class Employee(OrganizationElement):
def __init__(self, name: str, salary: float):
self.name = name
self.salary = salary
def accept(self, visitor: Visitor):
visitor.visit_employee(self)
class Department(OrganizationElement):
def __init__(self, name: str):
self.name = name
self.employees: List[Employee] = []
def add_employee(self, employee: Employee):
self.employees.append(employee)
def accept(self, visitor: Visitor):
visitor.visit_department(self)
for emp in self.employees:
emp.accept(visitor)
class SalaryReportVisitor(Visitor):
def __init__(self):
self.total = 0
def visit_employee(self, employee: Employee):
self.total += employee.salary
print(f"{employee.name}: ${employee.salary}")
def visit_department(self, department: Department):
print(f"\nDepartment: {department.name}")
if __name__ == "__main__":
dept = Department("Engineering")
dept.add_employee(Employee("Alice", 5000))
dept.add_employee(Employee("Bob", 6000))
visitor = SalaryReportVisitor()
dept.accept(visitor)
print(f"\nTotal salary: ${visitor.total}")
总结对比
| 模式 | 核心思想 | 使用场景 |
|---|---|---|
| 责任链 | 链式传递请求 | 多级审批、过滤器链 |
| 命令 | 封装请求为对象 | 撤销操作、队列请求 |
| 解释器 | 定义文法解释器 | 简单语言解析 |
| 迭代器 | 顺序访问聚合对象 | 遍历集合 |
| 中介者 | 封装对象交互 | 聊天室、MVC控制器 |
| 备忘录 | 捕获和恢复状态 | 撤销操作、游戏存档 |
| 观察者 | 一对多依赖通知 | 事件监听、消息订阅 |
| 状态 | 状态决定行为 | 订单状态、工作流 |
| 策略 | 封装可互换算法 | 支付方式、排序算法 |
| 模板方法 | 定义算法骨架 | 框架设计 |
| 访问者 | 分离操作与对象 | 编译器、报表生成 |
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)