13.1 本章概述
在本章中,我们将深入学习两种重要的行为型设计模式:备忘录模式(Memento Pattern)和解释器模式(Interpreter Pattern)。这两种模式在软件开发中有着独特的应用场景和价值。
13.1.1 学习目标
- 理解备忘录模式的核心思想和实现机制
- 掌握解释器模式的设计原理和应用场景
- 学会在实际项目中合理运用这两种模式
- 了解模式的优缺点和适用条件
- 掌握模式的高级应用技巧和性能优化
13.1.2 应用场景预览
备忘录模式常用于: - 撤销/重做功能实现 - 游戏存档系统 - 事务回滚机制 - 配置快照管理 - 版本控制系统
解释器模式常用于: - 领域特定语言(DSL) - 配置文件解析 - 规则引擎 - 表达式求值 - 简单脚本语言
13.2 备忘录模式(Memento Pattern)
13.2.1 模式定义
备忘录模式是一种行为型设计模式,它允许在不破坏封装性的前提下,捕获并外部化一个对象的内部状态,以便以后可以将该对象恢复到原先保存的状态。
13.2.2 模式动机
在软件开发中,我们经常需要实现撤销功能,或者在某些操作失败时回滚到之前的状态。直接访问对象的内部状态会破坏封装性,而备忘录模式提供了一种优雅的解决方案。
13.2.3 模式结构
备忘录模式包含以下角色:
- 发起人(Originator):创建备忘录对象,用于保存当前状态
- 备忘录(Memento):存储发起人的内部状态
- 管理者(Caretaker):负责保存备忘录,但不能操作或检查备忘录的内容
13.2.4 Python实现示例:文本编辑器
from abc import ABC, abstractmethod
from typing import List, Optional
import copy
import time
from dataclasses import dataclass
# 备忘录接口
class Memento(ABC):
"""备忘录抽象基类"""
@abstractmethod
def get_state(self):
"""获取状态(仅供发起人使用)"""
pass
@abstractmethod
def get_name(self) -> str:
"""获取备忘录名称"""
pass
@abstractmethod
def get_date(self) -> str:
"""获取创建时间"""
pass
# 具体备忘录
@dataclass
class TextEditorMemento(Memento):
"""文本编辑器备忘录"""
def __init__(self, state: dict, name: str = ""):
self._state = copy.deepcopy(state)
self._name = name or f"Auto-save {time.strftime('%Y-%m-%d %H:%M:%S')}"
self._date = time.strftime('%Y-%m-%d %H:%M:%S')
def get_state(self) -> dict:
return copy.deepcopy(self._state)
def get_name(self) -> str:
return self._name
def get_date(self) -> str:
return self._date
def __str__(self):
return f"Memento[{self._name}] - {self._date}"
# 发起人:文本编辑器
class TextEditor:
"""文本编辑器(发起人)"""
def __init__(self):
self._content = ""
self._cursor_position = 0
self._selection_start = 0
self._selection_end = 0
self._font_size = 12
self._font_family = "Arial"
self._is_bold = False
self._is_italic = False
self._zoom_level = 100
self._word_wrap = True
# 编辑历史
self._edit_count = 0
self._last_modified = time.time()
def type_text(self, text: str):
"""输入文本"""
# 如果有选中文本,先删除
if self._selection_start != self._selection_end:
self.delete_selection()
# 在光标位置插入文本
self._content = (self._content[:self._cursor_position] +
text +
self._content[self._cursor_position:])
self._cursor_position += len(text)
self._update_edit_info()
def delete_text(self, count: int = 1):
"""删除文本(向后删除)"""
if self._cursor_position > 0:
start = max(0, self._cursor_position - count)
self._content = (self._content[:start] +
self._content[self._cursor_position:])
self._cursor_position = start
self._update_edit_info()
def delete_selection(self):
"""删除选中的文本"""
if self._selection_start != self._selection_end:
start = min(self._selection_start, self._selection_end)
end = max(self._selection_start, self._selection_end)
self._content = self._content[:start] + self._content[end:]
self._cursor_position = start
self._selection_start = self._selection_end = start
self._update_edit_info()
def select_text(self, start: int, end: int):
"""选择文本"""
self._selection_start = max(0, min(start, len(self._content)))
self._selection_end = max(0, min(end, len(self._content)))
self._cursor_position = self._selection_end
def move_cursor(self, position: int):
"""移动光标"""
self._cursor_position = max(0, min(position, len(self._content)))
self._selection_start = self._selection_end = self._cursor_position
def set_font(self, family: str, size: int, bold: bool = False, italic: bool = False):
"""设置字体"""
self._font_family = family
self._font_size = size
self._is_bold = bold
self._is_italic = italic
self._update_edit_info()
def set_zoom(self, level: int):
"""设置缩放级别"""
self._zoom_level = max(50, min(200, level))
def set_word_wrap(self, enabled: bool):
"""设置自动换行"""
self._word_wrap = enabled
def _update_edit_info(self):
"""更新编辑信息"""
self._edit_count += 1
self._last_modified = time.time()
def save(self, name: str = "") -> Memento:
"""保存当前状态到备忘录"""
state = {
'content': self._content,
'cursor_position': self._cursor_position,
'selection_start': self._selection_start,
'selection_end': self._selection_end,
'font_size': self._font_size,
'font_family': self._font_family,
'is_bold': self._is_bold,
'is_italic': self._is_italic,
'zoom_level': self._zoom_level,
'word_wrap': self._word_wrap,
'edit_count': self._edit_count,
'last_modified': self._last_modified
}
return TextEditorMemento(state, name)
def restore(self, memento: Memento):
"""从备忘录恢复状态"""
if not isinstance(memento, TextEditorMemento):
raise ValueError("Invalid memento type")
state = memento.get_state()
self._content = state['content']
self._cursor_position = state['cursor_position']
self._selection_start = state['selection_start']
self._selection_end = state['selection_end']
self._font_size = state['font_size']
self._font_family = state['font_family']
self._is_bold = state['is_bold']
self._is_italic = state['is_italic']
self._zoom_level = state['zoom_level']
self._word_wrap = state['word_wrap']
self._edit_count = state['edit_count']
self._last_modified = state['last_modified']
def get_content(self) -> str:
return self._content
def get_cursor_position(self) -> int:
return self._cursor_position
def get_selection(self) -> tuple:
return (self._selection_start, self._selection_end)
def get_font_info(self) -> dict:
return {
'family': self._font_family,
'size': self._font_size,
'bold': self._is_bold,
'italic': self._is_italic
}
def get_view_info(self) -> dict:
return {
'zoom_level': self._zoom_level,
'word_wrap': self._word_wrap
}
def get_stats(self) -> dict:
return {
'character_count': len(self._content),
'word_count': len(self._content.split()),
'line_count': self._content.count('\n') + 1,
'edit_count': self._edit_count,
'last_modified': time.strftime('%Y-%m-%d %H:%M:%S',
time.localtime(self._last_modified))
}
def __str__(self):
preview = self._content[:50] + "..." if len(self._content) > 50 else self._content
return f"TextEditor[cursor={self._cursor_position}, content='{preview}']"
# 管理者:历史记录管理器
class HistoryManager:
"""历史记录管理器(管理者)"""
def __init__(self, max_history: int = 50):
self._mementos: List[Memento] = []
self._current_index = -1
self._max_history = max_history
self._auto_save_enabled = True
self._auto_save_interval = 30 # 秒
self._last_auto_save = 0
def save_state(self, memento: Memento):
"""保存状态"""
# 如果当前不在历史记录的末尾,删除后面的记录
if self._current_index < len(self._mementos) - 1:
self._mementos = self._mementos[:self._current_index + 1]
# 添加新的备忘录
self._mementos.append(memento)
self._current_index += 1
# 限制历史记录数量
if len(self._mementos) > self._max_history:
self._mementos.pop(0)
self._current_index -= 1
print(f"状态已保存: {memento.get_name()}")
def undo(self) -> Optional[Memento]:
"""撤销操作"""
if self._current_index > 0:
self._current_index -= 1
memento = self._mementos[self._current_index]
print(f"撤销到: {memento.get_name()}")
return memento
else:
print("无法撤销:已到达历史记录开始")
return None
def redo(self) -> Optional[Memento]:
"""重做操作"""
if self._current_index < len(self._mementos) - 1:
self._current_index += 1
memento = self._mementos[self._current_index]
print(f"重做到: {memento.get_name()}")
return memento
else:
print("无法重做:已到达历史记录末尾")
return None
def get_current_memento(self) -> Optional[Memento]:
"""获取当前备忘录"""
if 0 <= self._current_index < len(self._mementos):
return self._mementos[self._current_index]
return None
def get_history(self) -> List[str]:
"""获取历史记录列表"""
history = []
for i, memento in enumerate(self._mementos):
marker = " -> " if i == self._current_index else " "
history.append(f"{marker}{i}: {memento.get_name()} ({memento.get_date()})")
return history
def clear_history(self):
"""清空历史记录"""
self._mementos.clear()
self._current_index = -1
print("历史记录已清空")
def can_undo(self) -> bool:
"""是否可以撤销"""
return self._current_index > 0
def can_redo(self) -> bool:
"""是否可以重做"""
return self._current_index < len(self._mementos) - 1
def set_auto_save(self, enabled: bool, interval: int = 30):
"""设置自动保存"""
self._auto_save_enabled = enabled
self._auto_save_interval = interval
def should_auto_save(self) -> bool:
"""是否应该自动保存"""
if not self._auto_save_enabled:
return False
current_time = time.time()
if current_time - self._last_auto_save >= self._auto_save_interval:
self._last_auto_save = current_time
return True
return False
def get_stats(self) -> dict:
"""获取统计信息"""
return {
'total_saves': len(self._mementos),
'current_position': self._current_index + 1,
'can_undo': self.can_undo(),
'can_redo': self.can_redo(),
'auto_save_enabled': self._auto_save_enabled,
'auto_save_interval': self._auto_save_interval
}
# 文本编辑器应用
class TextEditorApp:
"""文本编辑器应用"""
def __init__(self):
self.editor = TextEditor()
self.history = HistoryManager()
# 保存初始状态
initial_state = self.editor.save("初始状态")
self.history.save_state(initial_state)
def type_text(self, text: str):
"""输入文本"""
self.editor.type_text(text)
self._check_auto_save()
def delete_text(self, count: int = 1):
"""删除文本"""
self.editor.delete_text(count)
self._check_auto_save()
def select_and_delete(self, start: int, end: int):
"""选择并删除文本"""
self.editor.select_text(start, end)
self.editor.delete_selection()
self._check_auto_save()
def format_text(self, family: str, size: int, bold: bool = False, italic: bool = False):
"""格式化文本"""
self.editor.set_font(family, size, bold, italic)
self._check_auto_save()
def save_checkpoint(self, name: str = ""):
"""手动保存检查点"""
memento = self.editor.save(name or "手动保存")
self.history.save_state(memento)
def undo(self):
"""撤销"""
memento = self.history.undo()
if memento:
self.editor.restore(memento)
def redo(self):
"""重做"""
memento = self.history.redo()
if memento:
self.editor.restore(memento)
def _check_auto_save(self):
"""检查是否需要自动保存"""
if self.history.should_auto_save():
memento = self.editor.save("自动保存")
self.history.save_state(memento)
def show_status(self):
"""显示状态信息"""
print("\n=== 编辑器状态 ===")
print(f"内容: '{self.editor.get_content()}'")
print(f"光标位置: {self.editor.get_cursor_position()}")
print(f"选择范围: {self.editor.get_selection()}")
print(f"字体信息: {self.editor.get_font_info()}")
print(f"视图信息: {self.editor.get_view_info()}")
print(f"统计信息: {self.editor.get_stats()}")
print("\n=== 历史记录 ===")
history = self.history.get_history()
for record in history:
print(record)
print(f"\n=== 历史统计 ===")
stats = self.history.get_stats()
for key, value in stats.items():
print(f"{key}: {value}")
# 演示备忘录模式
def demonstrate_memento_pattern():
print("=== 备忘录模式演示:文本编辑器 ===")
app = TextEditorApp()
# 编辑操作
print("\n1. 输入文本")
app.type_text("Hello World!")
app.save_checkpoint("输入Hello World")
print("\n2. 继续编辑")
app.type_text(" This is a test.")
app.save_checkpoint("添加测试文本")
print("\n3. 格式化文本")
app.format_text("Times New Roman", 14, bold=True)
app.save_checkpoint("设置字体格式")
print("\n4. 选择并删除部分文本")
app.select_and_delete(5, 11) # 删除"World"
app.save_checkpoint("删除World")
app.show_status()
# 撤销操作
print("\n\n=== 撤销操作 ===")
app.undo() # 撤销删除
app.undo() # 撤销格式化
app.show_status()
# 重做操作
print("\n\n=== 重做操作 ===")
app.redo() # 重做格式化
app.show_status()
# 测试自动保存
print("\n\n=== 测试自动保存 ===")
app.history.set_auto_save(True, 1) # 1秒自动保存
app.type_text(" Auto-save test.")
time.sleep(1.1)
app.type_text(" Another change.")
app.show_status()
if __name__ == "__main__":
demonstrate_memento_pattern()
13.2.5 Java实现示例:游戏存档系统
import java.util.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.io.*;
// 备忘录接口
interface GameMemento {
String getName();
LocalDateTime getTimestamp();
GameState getState();
}
// 游戏状态数据类
class GameState implements Serializable {
private static final long serialVersionUID = 1L;
private int level;
private int score;
private int lives;
private double playerX;
private double playerY;
private int health;
private int mana;
private List<String> inventory;
private Map<String, Integer> skills;
private String currentMap;
private Map<String, Object> gameFlags;
public GameState() {
this.inventory = new ArrayList<>();
this.skills = new HashMap<>();
this.gameFlags = new HashMap<>();
}
// 深拷贝构造函数
public GameState(GameState other) {
this.level = other.level;
this.score = other.score;
this.lives = other.lives;
this.playerX = other.playerX;
this.playerY = other.playerY;
this.health = other.health;
this.mana = other.mana;
this.inventory = new ArrayList<>(other.inventory);
this.skills = new HashMap<>(other.skills);
this.currentMap = other.currentMap;
this.gameFlags = new HashMap<>(other.gameFlags);
}
// Getters and Setters
public int getLevel() { return level; }
public void setLevel(int level) { this.level = level; }
public int getScore() { return score; }
public void setScore(int score) { this.score = score; }
public int getLives() { return lives; }
public void setLives(int lives) { this.lives = lives; }
public double getPlayerX() { return playerX; }
public void setPlayerX(double playerX) { this.playerX = playerX; }
public double getPlayerY() { return playerY; }
public void setPlayerY(double playerY) { this.playerY = playerY; }
public int getHealth() { return health; }
public void setHealth(int health) { this.health = health; }
public int getMana() { return mana; }
public void setMana(int mana) { this.mana = mana; }
public List<String> getInventory() { return new ArrayList<>(inventory); }
public void setInventory(List<String> inventory) { this.inventory = new ArrayList<>(inventory); }
public Map<String, Integer> getSkills() { return new HashMap<>(skills); }
public void setSkills(Map<String, Integer> skills) { this.skills = new HashMap<>(skills); }
public String getCurrentMap() { return currentMap; }
public void setCurrentMap(String currentMap) { this.currentMap = currentMap; }
public Map<String, Object> getGameFlags() { return new HashMap<>(gameFlags); }
public void setGameFlags(Map<String, Object> gameFlags) { this.gameFlags = new HashMap<>(gameFlags); }
@Override
public String toString() {
return String.format("GameState[Level=%d, Score=%d, Lives=%d, Health=%d, Position=(%.1f,%.1f)]",
level, score, lives, health, playerX, playerY);
}
}
// 具体备忘录实现
class ConcreteGameMemento implements GameMemento {
private final String name;
private final LocalDateTime timestamp;
private final GameState state;
public ConcreteGameMemento(String name, GameState state) {
this.name = name;
this.timestamp = LocalDateTime.now();
this.state = new GameState(state); // 深拷贝
}
@Override
public String getName() {
return name;
}
@Override
public LocalDateTime getTimestamp() {
return timestamp;
}
@Override
public GameState getState() {
return new GameState(state); // 返回深拷贝
}
@Override
public String toString() {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return String.format("%s [%s]", name, timestamp.format(formatter));
}
}
// 发起人:游戏引擎
class GameEngine {
private GameState currentState;
private Random random;
public GameEngine() {
this.currentState = new GameState();
this.random = new Random();
initializeGame();
}
private void initializeGame() {
currentState.setLevel(1);
currentState.setScore(0);
currentState.setLives(3);
currentState.setPlayerX(0.0);
currentState.setPlayerY(0.0);
currentState.setHealth(100);
currentState.setMana(50);
currentState.setCurrentMap("StartingArea");
// 初始装备
List<String> initialInventory = Arrays.asList("Sword", "Health Potion");
currentState.setInventory(initialInventory);
// 初始技能
Map<String, Integer> initialSkills = new HashMap<>();
initialSkills.put("Attack", 1);
initialSkills.put("Defense", 1);
currentState.setSkills(initialSkills);
}
// 游戏操作方法
public void movePlayer(double deltaX, double deltaY) {
currentState.setPlayerX(currentState.getPlayerX() + deltaX);
currentState.setPlayerY(currentState.getPlayerY() + deltaY);
System.out.printf("玩家移动到位置: (%.1f, %.1f)\n",
currentState.getPlayerX(), currentState.getPlayerY());
}
public void gainExperience(int exp) {
currentState.setScore(currentState.getScore() + exp);
// 检查升级
int newLevel = (currentState.getScore() / 1000) + 1;
if (newLevel > currentState.getLevel()) {
levelUp(newLevel);
}
System.out.printf("获得经验: %d, 总分: %d\n", exp, currentState.getScore());
}
private void levelUp(int newLevel) {
currentState.setLevel(newLevel);
currentState.setHealth(Math.min(100, currentState.getHealth() + 20));
currentState.setMana(Math.min(100, currentState.getMana() + 10));
// 提升技能
Map<String, Integer> skills = currentState.getSkills();
skills.replaceAll((k, v) -> v + 1);
currentState.setSkills(skills);
System.out.printf("恭喜升级到 %d 级!\n", newLevel);
}
public void takeDamage(int damage) {
int newHealth = Math.max(0, currentState.getHealth() - damage);
currentState.setHealth(newHealth);
if (newHealth == 0) {
loseLife();
}
System.out.printf("受到伤害: %d, 剩余生命值: %d\n", damage, newHealth);
}
private void loseLife() {
int newLives = currentState.getLives() - 1;
currentState.setLives(newLives);
if (newLives > 0) {
currentState.setHealth(100); // 复活时恢复满血
System.out.printf("失去一条生命,剩余生命: %d\n", newLives);
} else {
System.out.println("游戏结束!");
}
}
public void addItem(String item) {
List<String> inventory = currentState.getInventory();
inventory.add(item);
currentState.setInventory(inventory);
System.out.printf("获得物品: %s\n", item);
}
public void useItem(String item) {
List<String> inventory = currentState.getInventory();
if (inventory.remove(item)) {
currentState.setInventory(inventory);
// 使用物品效果
switch (item) {
case "Health Potion":
int newHealth = Math.min(100, currentState.getHealth() + 30);
currentState.setHealth(newHealth);
System.out.printf("使用生命药水,生命值恢复到: %d\n", newHealth);
break;
case "Mana Potion":
int newMana = Math.min(100, currentState.getMana() + 25);
currentState.setMana(newMana);
System.out.printf("使用魔法药水,魔法值恢复到: %d\n", newMana);
break;
default:
System.out.printf("使用了物品: %s\n", item);
}
} else {
System.out.printf("背包中没有物品: %s\n", item);
}
}
public void changeMap(String mapName) {
currentState.setCurrentMap(mapName);
System.out.printf("进入地图: %s\n", mapName);
}
public void setGameFlag(String flag, Object value) {
Map<String, Object> flags = currentState.getGameFlags();
flags.put(flag, value);
currentState.setGameFlags(flags);
System.out.printf("设置游戏标志: %s = %s\n", flag, value);
}
// 备忘录相关方法
public GameMemento createSave(String saveName) {
return new ConcreteGameMemento(saveName, currentState);
}
public void loadSave(GameMemento memento) {
this.currentState = memento.getState();
System.out.printf("加载存档: %s\n", memento.getName());
}
// 获取当前状态信息
public GameState getCurrentState() {
return new GameState(currentState);
}
public void printStatus() {
System.out.println("\n=== 游戏状态 ===");
System.out.println(currentState);
System.out.printf("当前地图: %s\n", currentState.getCurrentMap());
System.out.printf("背包物品: %s\n", currentState.getInventory());
System.out.printf("技能等级: %s\n", currentState.getSkills());
if (!currentState.getGameFlags().isEmpty()) {
System.out.printf("游戏标志: %s\n", currentState.getGameFlags());
}
}
public boolean isGameOver() {
return currentState.getLives() <= 0;
}
}
// 管理者:存档管理器
class SaveManager {
private List<GameMemento> saves;
private int maxSaves;
private boolean autoSaveEnabled;
private int autoSaveInterval; // 操作次数间隔
private int operationCount;
public SaveManager(int maxSaves) {
this.saves = new ArrayList<>();
this.maxSaves = maxSaves;
this.autoSaveEnabled = true;
this.autoSaveInterval = 5; // 每5个操作自动保存
this.operationCount = 0;
}
public void addSave(GameMemento save) {
saves.add(save);
// 限制存档数量
if (saves.size() > maxSaves) {
saves.remove(0);
}
System.out.printf("存档已保存: %s\n", save.getName());
}
public GameMemento getSave(int index) {
if (index >= 0 && index < saves.size()) {
return saves.get(index);
}
return null;
}
public GameMemento getLatestSave() {
return saves.isEmpty() ? null : saves.get(saves.size() - 1);
}
public List<GameMemento> getAllSaves() {
return new ArrayList<>(saves);
}
public void deleteSave(int index) {
if (index >= 0 && index < saves.size()) {
GameMemento removed = saves.remove(index);
System.out.printf("删除存档: %s\n", removed.getName());
}
}
public void clearAllSaves() {
saves.clear();
System.out.println("所有存档已清除");
}
public void incrementOperationCount() {
operationCount++;
}
public boolean shouldAutoSave() {
return autoSaveEnabled && (operationCount % autoSaveInterval == 0);
}
public void setAutoSave(boolean enabled, int interval) {
this.autoSaveEnabled = enabled;
this.autoSaveInterval = interval;
}
public void printSaveList() {
System.out.println("\n=== 存档列表 ===");
if (saves.isEmpty()) {
System.out.println("暂无存档");
} else {
for (int i = 0; i < saves.size(); i++) {
System.out.printf("%d. %s\n", i + 1, saves.get(i));
}
}
}
public int getSaveCount() {
return saves.size();
}
}
// 游戏应用
class GameApplication {
private GameEngine gameEngine;
private SaveManager saveManager;
public GameApplication() {
this.gameEngine = new GameEngine();
this.saveManager = new SaveManager(10);
// 创建初始存档
GameMemento initialSave = gameEngine.createSave("游戏开始");
saveManager.addSave(initialSave);
}
public void performAction(String action, Object... params) {
saveManager.incrementOperationCount();
switch (action.toLowerCase()) {
case "move":
if (params.length >= 2) {
gameEngine.movePlayer((Double) params[0], (Double) params[1]);
}
break;
case "fight":
simulateFight();
break;
case "explore":
simulateExploration();
break;
case "use_item":
if (params.length >= 1) {
gameEngine.useItem((String) params[0]);
}
break;
case "change_map":
if (params.length >= 1) {
gameEngine.changeMap((String) params[0]);
}
break;
}
// 检查自动保存
if (saveManager.shouldAutoSave()) {
GameMemento autoSave = gameEngine.createSave("自动保存 #" + saveManager.getSaveCount());
saveManager.addSave(autoSave);
}
}
private void simulateFight() {
Random random = new Random();
// 模拟战斗
int damage = random.nextInt(20) + 10;
gameEngine.takeDamage(damage);
if (!gameEngine.isGameOver()) {
int exp = random.nextInt(100) + 50;
gameEngine.gainExperience(exp);
// 随机掉落物品
if (random.nextDouble() < 0.3) {
String[] items = {"Health Potion", "Mana Potion", "Magic Scroll", "Gold Coin"};
String item = items[random.nextInt(items.length)];
gameEngine.addItem(item);
}
}
}
private void simulateExploration() {
Random random = new Random();
// 随机移动
double deltaX = (random.nextDouble() - 0.5) * 20;
double deltaY = (random.nextDouble() - 0.5) * 20;
gameEngine.movePlayer(deltaX, deltaY);
// 随机事件
double eventChance = random.nextDouble();
if (eventChance < 0.2) {
// 发现宝箱
String[] treasures = {"Health Potion", "Mana Potion", "Rare Gem", "Ancient Artifact"};
String treasure = treasures[random.nextInt(treasures.length)];
gameEngine.addItem(treasure);
System.out.println("发现宝箱!");
} else if (eventChance < 0.4) {
// 遭遇敌人
System.out.println("遭遇敌人!");
simulateFight();
} else {
// 获得少量经验
gameEngine.gainExperience(random.nextInt(30) + 10);
}
}
public void manualSave(String saveName) {
GameMemento save = gameEngine.createSave(saveName);
saveManager.addSave(save);
}
public void loadSave(int saveIndex) {
GameMemento save = saveManager.getSave(saveIndex - 1); // 用户输入从1开始
if (save != null) {
gameEngine.loadSave(save);
} else {
System.out.println("无效的存档索引");
}
}
public void showStatus() {
gameEngine.printStatus();
saveManager.printSaveList();
}
public boolean isGameOver() {
return gameEngine.isGameOver();
}
public SaveManager getSaveManager() {
return saveManager;
}
}
// 演示类
public class MementoPatternDemo {
public static void main(String[] args) {
System.out.println("=== 备忘录模式演示:游戏存档系统 ===");
GameApplication game = new GameApplication();
// 游戏流程演示
System.out.println("\n--- 开始游戏 ---");
game.showStatus();
// 进行一些游戏操作
System.out.println("\n--- 探索和战斗 ---");
game.performAction("explore");
game.performAction("fight");
game.performAction("move", 10.0, 5.0);
game.manualSave("第一次探索后");
game.performAction("explore");
game.performAction("explore");
game.performAction("fight");
game.manualSave("连续探索后");
game.showStatus();
// 继续游戏
System.out.println("\n--- 继续冒险 ---");
game.performAction("change_map", "Forest");
game.performAction("explore");
game.performAction("fight");
game.performAction("use_item", "Health Potion");
game.showStatus();
// 演示加载存档
System.out.println("\n--- 加载之前的存档 ---");
game.loadSave(2); // 加载"第一次探索后"存档
game.showStatus();
// 从加载点继续游戏
System.out.println("\n--- 从存档点重新开始 ---");
game.performAction("change_map", "Cave");
game.performAction("explore");
game.manualSave("洞穴探索");
game.showStatus();
System.out.println("\n游戏演示完成!");
}
}
13.2.6 备忘录模式的优缺点
优点: 1. 封装性保护:不破坏对象的封装性,外部无法直接访问对象内部状态 2. 状态恢复:提供了简单的状态恢复机制 3. 撤销支持:天然支持撤销/重做功能 4. 快照管理:可以创建对象状态的快照 5. 解耦合:发起人和管理者之间解耦
缺点: 1. 内存开销:需要存储大量的状态信息 2. 性能影响:频繁创建备忘录可能影响性能 3. 复杂性增加:增加了系统的复杂性 4. 生命周期管理:需要合理管理备忘录的生命周期
13.2.7 备忘录模式的适用场景
- 撤销/重做功能:文本编辑器、图形编辑器等
- 事务处理:数据库事务回滚
- 游戏存档:游戏状态保存和加载
- 配置管理:系统配置的备份和恢复
- 版本控制:代码版本管理系统
- 工作流程:复杂业务流程的状态管理
13.3 解释器模式(Interpreter Pattern)
13.3.1 模式定义
解释器模式是一种行为型设计模式,它定义了一种语言的文法表示,并定义一个解释器来处理这种语言中的句子。该模式用于构建一个简单的语言解释器。
13.3.2 模式动机
在软件开发中,我们经常需要处理各种规则、表达式或简单的领域特定语言(DSL)。解释器模式提供了一种将语言的语法规则表示为类层次结构的方法,使得可以轻松地扩展和修改语言。
13.3.3 模式结构
解释器模式包含以下角色:
- 抽象表达式(AbstractExpression):定义解释操作的接口
- 终结符表达式(TerminalExpression):实现文法中终结符相关的解释操作
- 非终结符表达式(NonterminalExpression):实现文法中非终结符相关的解释操作
- 上下文(Context):包含解释器之外的全局信息
- 客户端(Client):构建抽象语法树并调用解释操作
13.3.4 Python实现示例:数学表达式解释器
from abc import ABC, abstractmethod
from typing import Dict, List, Union
import re
import math
import operator
# 上下文类
class Context:
"""解释器上下文"""
def __init__(self):
self.variables: Dict[str, float] = {}
self.functions: Dict[str, callable] = {
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'log': math.log,
'sqrt': math.sqrt,
'abs': abs,
'pow': pow,
'exp': math.exp
}
self.constants: Dict[str, float] = {
'pi': math.pi,
'e': math.e
}
def set_variable(self, name: str, value: float):
"""设置变量值"""
self.variables[name] = value
def get_variable(self, name: str) -> float:
"""获取变量值"""
if name in self.variables:
return self.variables[name]
elif name in self.constants:
return self.constants[name]
else:
raise ValueError(f"未定义的变量: {name}")
def has_variable(self, name: str) -> bool:
"""检查变量是否存在"""
return name in self.variables or name in self.constants
def get_function(self, name: str) -> callable:
"""获取函数"""
if name in self.functions:
return self.functions[name]
else:
raise ValueError(f"未定义的函数: {name}")
def has_function(self, name: str) -> bool:
"""检查函数是否存在"""
return name in self.functions
def clear_variables(self):
"""清空变量"""
self.variables.clear()
def get_all_variables(self) -> Dict[str, float]:
"""获取所有变量"""
result = self.variables.copy()
result.update(self.constants)
return result
# 抽象表达式
class Expression(ABC):
"""抽象表达式"""
@abstractmethod
def interpret(self, context: Context) -> float:
"""解释表达式"""
pass
@abstractmethod
def __str__(self) -> str:
"""字符串表示"""
pass
# 终结符表达式:数字
class NumberExpression(Expression):
"""数字表达式"""
def __init__(self, value: float):
self.value = value
def interpret(self, context: Context) -> float:
return self.value
def __str__(self) -> str:
return str(self.value)
# 终结符表达式:变量
class VariableExpression(Expression):
"""变量表达式"""
def __init__(self, name: str):
self.name = name
def interpret(self, context: Context) -> float:
return context.get_variable(self.name)
def __str__(self) -> str:
return self.name
# 非终结符表达式:二元操作
class BinaryExpression(Expression):
"""二元表达式基类"""
def __init__(self, left: Expression, right: Expression):
self.left = left
self.right = right
@abstractmethod
def operate(self, left_val: float, right_val: float) -> float:
"""执行操作"""
pass
def interpret(self, context: Context) -> float:
left_val = self.left.interpret(context)
right_val = self.right.interpret(context)
return self.operate(left_val, right_val)
# 具体二元表达式
class AddExpression(BinaryExpression):
"""加法表达式"""
def operate(self, left_val: float, right_val: float) -> float:
return left_val + right_val
def __str__(self) -> str:
return f"({self.left} + {self.right})"
class SubtractExpression(BinaryExpression):
"""减法表达式"""
def operate(self, left_val: float, right_val: float) -> float:
return left_val - right_val
def __str__(self) -> str:
return f"({self.left} - {self.right})"
class MultiplyExpression(BinaryExpression):
"""乘法表达式"""
def operate(self, left_val: float, right_val: float) -> float:
return left_val * right_val
def __str__(self) -> str:
return f"({self.left} * {self.right})"
class DivideExpression(BinaryExpression):
"""除法表达式"""
def operate(self, left_val: float, right_val: float) -> float:
if right_val == 0:
raise ValueError("除零错误")
return left_val / right_val
def __str__(self) -> str:
return f"({self.left} / {self.right})"
class PowerExpression(BinaryExpression):
"""幂运算表达式"""
def operate(self, left_val: float, right_val: float) -> float:
return left_val ** right_val
def __str__(self) -> str:
return f"({self.left} ^ {self.right})"
# 非终结符表达式:一元操作
class UnaryExpression(Expression):
"""一元表达式基类"""
def __init__(self, operand: Expression):
self.operand = operand
@abstractmethod
def operate(self, value: float) -> float:
"""执行操作"""
pass
def interpret(self, context: Context) -> float:
value = self.operand.interpret(context)
return self.operate(value)
class NegateExpression(UnaryExpression):
"""取负表达式"""
def operate(self, value: float) -> float:
return -value
def __str__(self) -> str:
return f"(-{self.operand})"
# 函数调用表达式
class FunctionExpression(Expression):
"""函数调用表达式"""
def __init__(self, function_name: str, arguments: List[Expression]):
self.function_name = function_name
self.arguments = arguments
def interpret(self, context: Context) -> float:
func = context.get_function(self.function_name)
args = [arg.interpret(context) for arg in self.arguments]
try:
return func(*args)
except Exception as e:
raise ValueError(f"函数 {self.function_name} 调用错误: {e}")
def __str__(self) -> str:
args_str = ", ".join(str(arg) for arg in self.arguments)
return f"{self.function_name}({args_str})"
# 表达式解析器
class ExpressionParser:
"""表达式解析器"""
def __init__(self):
self.operators = {
'+': (1, AddExpression),
'-': (1, SubtractExpression),
'*': (2, MultiplyExpression),
'/': (2, DivideExpression),
'^': (3, PowerExpression)
}
def parse(self, expression: str) -> Expression:
"""解析表达式字符串"""
tokens = self._tokenize(expression)
return self._parse_expression(tokens)
def _tokenize(self, expression: str) -> List[str]:
"""词法分析"""
# 移除空格
expression = re.sub(r'\s+', '', expression)
# 定义token模式
token_pattern = r'(\d+\.?\d*|[a-zA-Z_]\w*|[+\-*/^()]|,)'
tokens = re.findall(token_pattern, expression)
if not tokens:
raise ValueError("无效的表达式")
return tokens
def _parse_expression(self, tokens: List[str]) -> Expression:
"""解析表达式(处理加减法)"""
left = self._parse_term(tokens)
while tokens and tokens[0] in ['+', '-']:
op = tokens.pop(0)
right = self._parse_term(tokens)
if op == '+':
left = AddExpression(left, right)
else:
left = SubtractExpression(left, right)
return left
def _parse_term(self, tokens: List[str]) -> Expression:
"""解析项(处理乘除法)"""
left = self._parse_factor(tokens)
while tokens and tokens[0] in ['*', '/']:
op = tokens.pop(0)
right = self._parse_factor(tokens)
if op == '*':
left = MultiplyExpression(left, right)
else:
left = DivideExpression(left, right)
return left
def _parse_factor(self, tokens: List[str]) -> Expression:
"""解析因子(处理幂运算、括号、函数、变量、数字)"""
if not tokens:
raise ValueError("意外的表达式结束")
token = tokens[0]
# 处理负号
if token == '-':
tokens.pop(0)
operand = self._parse_factor(tokens)
return NegateExpression(operand)
# 处理括号
if token == '(':
tokens.pop(0) # 移除 '('
expr = self._parse_expression(tokens)
if not tokens or tokens.pop(0) != ')':
raise ValueError("缺少右括号")
# 检查幂运算
if tokens and tokens[0] == '^':
tokens.pop(0)
right = self._parse_factor(tokens)
return PowerExpression(expr, right)
return expr
# 处理数字
if re.match(r'^\d+\.?\d*$', token):
tokens.pop(0)
expr = NumberExpression(float(token))
# 检查幂运算
if tokens and tokens[0] == '^':
tokens.pop(0)
right = self._parse_factor(tokens)
return PowerExpression(expr, right)
return expr
# 处理变量和函数
if re.match(r'^[a-zA-Z_]\w*$', token):
tokens.pop(0)
# 检查是否是函数调用
if tokens and tokens[0] == '(':
tokens.pop(0) # 移除 '('
# 解析参数
arguments = []
if tokens and tokens[0] != ')':
arguments.append(self._parse_expression(tokens))
while tokens and tokens[0] == ',':
tokens.pop(0) # 移除 ','
arguments.append(self._parse_expression(tokens))
if not tokens or tokens.pop(0) != ')':
raise ValueError("缺少右括号")
expr = FunctionExpression(token, arguments)
else:
expr = VariableExpression(token)
# 检查幂运算
if tokens and tokens[0] == '^':
tokens.pop(0)
right = self._parse_factor(tokens)
return PowerExpression(expr, right)
return expr
raise ValueError(f"无效的token: {token}")
# 数学表达式计算器
class MathCalculator:
"""数学表达式计算器"""
def __init__(self):
self.context = Context()
self.parser = ExpressionParser()
self.history: List[tuple] = [] # (expression_str, result)
def set_variable(self, name: str, value: float):
"""设置变量"""
self.context.set_variable(name, value)
print(f"设置变量: {name} = {value}")
def evaluate(self, expression_str: str) -> float:
"""计算表达式"""
try:
expression = self.parser.parse(expression_str)
result = expression.interpret(self.context)
# 记录历史
self.history.append((expression_str, result))
print(f"表达式: {expression_str}")
print(f"解析后: {expression}")
print(f"结果: {result}")
return result
except Exception as e:
print(f"计算错误: {e}")
raise
def show_variables(self):
"""显示所有变量"""
variables = self.context.get_all_variables()
if variables:
print("\n当前变量:")
for name, value in variables.items():
print(f" {name} = {value}")
else:
print("\n暂无变量")
def show_history(self):
"""显示计算历史"""
if self.history:
print("\n计算历史:")
for i, (expr, result) in enumerate(self.history, 1):
print(f" {i}. {expr} = {result}")
else:
print("\n暂无计算历史")
def clear_history(self):
"""清空历史"""
self.history.clear()
print("计算历史已清空")
def clear_variables(self):
"""清空变量"""
self.context.clear_variables()
print("变量已清空")
# 演示解释器模式
def demonstrate_interpreter_pattern():
print("=== 解释器模式演示:数学表达式计算器 ===")
calculator = MathCalculator()
# 基本运算
print("\n1. 基本运算")
calculator.evaluate("2 + 3 * 4")
calculator.evaluate("(2 + 3) * 4")
calculator.evaluate("10 / 2 - 3")
calculator.evaluate("2 ^ 3 + 1")
# 变量使用
print("\n2. 变量使用")
calculator.set_variable("x", 5)
calculator.set_variable("y", 3)
calculator.evaluate("x + y")
calculator.evaluate("x * y - 2")
calculator.evaluate("x ^ 2 + y ^ 2")
# 函数调用
print("\n3. 函数调用")
calculator.evaluate("sin(pi / 2)")
calculator.evaluate("cos(0)")
calculator.evaluate("sqrt(16)")
calculator.evaluate("log(e)")
calculator.evaluate("pow(2, 3)")
# 复杂表达式
print("\n4. 复杂表达式")
calculator.set_variable("a", 2)
calculator.set_variable("b", 3)
calculator.evaluate("sqrt(a^2 + b^2)")
calculator.evaluate("sin(pi * a / 4) + cos(pi * b / 6)")
# 显示状态
calculator.show_variables()
calculator.show_history()
if __name__ == "__main__":
demonstrate_interpreter_pattern()
13.3.5 Go实现示例:简单查询语言
package main
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
)
// Context 上下文
type Context struct {
Data map[string]interface{}
}
// NewContext 创建新的上下文
func NewContext() *Context {
return &Context{
Data: make(map[string]interface{}),
}
}
// Set 设置数据
func (c *Context) Set(key string, value interface{}) {
c.Data[key] = value
}
// Get 获取数据
func (c *Context) Get(key string) (interface{}, bool) {
value, exists := c.Data[key]
return value, exists
}
// Expression 抽象表达式接口
type Expression interface {
Interpret(context *Context) (interface{}, error)
String() string
}
// LiteralExpression 字面量表达式
type LiteralExpression struct {
Value interface{}
}
func (e *LiteralExpression) Interpret(context *Context) (interface{}, error) {
return e.Value, nil
}
func (e *LiteralExpression) String() string {
return fmt.Sprintf("%v", e.Value)
}
// VariableExpression 变量表达式
type VariableExpression struct {
Name string
}
func (e *VariableExpression) Interpret(context *Context) (interface{}, error) {
value, exists := context.Get(e.Name)
if !exists {
return nil, fmt.Errorf("变量 %s 未定义", e.Name)
}
return value, nil
}
func (e *VariableExpression) String() string {
return e.Name
}
// ComparisonExpression 比较表达式
type ComparisonExpression struct {
Left Expression
Operator string
Right Expression
}
func (e *ComparisonExpression) Interpret(context *Context) (interface{}, error) {
leftValue, err := e.Left.Interpret(context)
if err != nil {
return nil, err
}
rightValue, err := e.Right.Interpret(context)
if err != nil {
return nil, err
}
switch e.Operator {
case "=":
return leftValue == rightValue, nil
case "!=":
return leftValue != rightValue, nil
case ">":
return compareNumbers(leftValue, rightValue, ">"), nil
case "<":
return compareNumbers(leftValue, rightValue, "<"), nil
case ">=":
return compareNumbers(leftValue, rightValue, ">="), nil
case "<=":
return compareNumbers(leftValue, rightValue, "<="), nil
case "LIKE":
return matchPattern(leftValue, rightValue), nil
default:
return nil, fmt.Errorf("不支持的操作符: %s", e.Operator)
}
}
func (e *ComparisonExpression) String() string {
return fmt.Sprintf("(%s %s %s)", e.Left.String(), e.Operator, e.Right.String())
}
// LogicalExpression 逻辑表达式
type LogicalExpression struct {
Left Expression
Operator string
Right Expression
}
func (e *LogicalExpression) Interpret(context *Context) (interface{}, error) {
leftValue, err := e.Left.Interpret(context)
if err != nil {
return nil, err
}
leftBool, ok := leftValue.(bool)
if !ok {
return nil, fmt.Errorf("逻辑操作需要布尔值")
}
switch e.Operator {
case "AND":
if !leftBool {
return false, nil // 短路求值
}
rightValue, err := e.Right.Interpret(context)
if err != nil {
return nil, err
}
rightBool, ok := rightValue.(bool)
if !ok {
return nil, fmt.Errorf("逻辑操作需要布尔值")
}
return leftBool && rightBool, nil
case "OR":
if leftBool {
return true, nil // 短路求值
}
rightValue, err := e.Right.Interpret(context)
if err != nil {
return nil, err
}
rightBool, ok := rightValue.(bool)
if !ok {
return nil, fmt.Errorf("逻辑操作需要布尔值")
}
return leftBool || rightBool, nil
default:
return nil, fmt.Errorf("不支持的逻辑操作符: %s", e.Operator)
}
}
func (e *LogicalExpression) String() string {
return fmt.Sprintf("(%s %s %s)", e.Left.String(), e.Operator, e.Right.String())
}
// NotExpression 非表达式
type NotExpression struct {
Expression Expression
}
func (e *NotExpression) Interpret(context *Context) (interface{}, error) {
value, err := e.Expression.Interpret(context)
if err != nil {
return nil, err
}
boolValue, ok := value.(bool)
if !ok {
return nil, fmt.Errorf("NOT操作需要布尔值")
}
return !boolValue, nil
}
func (e *NotExpression) String() string {
return fmt.Sprintf("(NOT %s)", e.Expression.String())
}
// 辅助函数
func compareNumbers(left, right interface{}, operator string) bool {
leftNum, leftOk := toFloat64(left)
rightNum, rightOk := toFloat64(right)
if !leftOk || !rightOk {
return false
}
switch operator {
case ">":
return leftNum > rightNum
case "<":
return leftNum < rightNum
case ">=":
return leftNum >= rightNum
case "<=":
return leftNum <= rightNum
default:
return false
}
}
func toFloat64(value interface{}) (float64, bool) {
switch v := value.(type) {
case int:
return float64(v), true
case int64:
return float64(v), true
case float32:
return float64(v), true
case float64:
return v, true
case string:
if num, err := strconv.ParseFloat(v, 64); err == nil {
return num, true
}
}
return 0, false
}
func matchPattern(value, pattern interface{}) bool {
valueStr, ok1 := value.(string)
patternStr, ok2 := pattern.(string)
if !ok1 || !ok2 {
return false
}
// 简单的通配符匹配(* 表示任意字符)
patternStr = strings.ReplaceAll(patternStr, "*", ".*")
matched, _ := regexp.MatchString("^" + patternStr + "$", valueStr)
return matched
}
// QueryParser 查询解析器
type QueryParser struct {
tokens []string
pos int
}
// NewQueryParser 创建查询解析器
func NewQueryParser() *QueryParser {
return &QueryParser{}
}
// Parse 解析查询字符串
func (p *QueryParser) Parse(query string) (Expression, error) {
p.tokens = p.tokenize(query)
p.pos = 0
if len(p.tokens) == 0 {
return nil, fmt.Errorf("空查询")
}
expr, err := p.parseOrExpression()
if err != nil {
return nil, err
}
if p.pos < len(p.tokens) {
return nil, fmt.Errorf("查询解析不完整,剩余token: %v", p.tokens[p.pos:])
}
return expr, nil
}
func (p *QueryParser) tokenize(query string) []string {
// 简单的词法分析
query = strings.TrimSpace(query)
pattern := `(\w+|[><=!]+|\(|\)|"[^"]*"|'[^']*')`
re := regexp.MustCompile(pattern)
return re.FindAllString(query, -1)
}
func (p *QueryParser) parseOrExpression() (Expression, error) {
left, err := p.parseAndExpression()
if err != nil {
return nil, err
}
for p.pos < len(p.tokens) && strings.ToUpper(p.tokens[p.pos]) == "OR" {
p.pos++ // 跳过 OR
right, err := p.parseAndExpression()
if err != nil {
return nil, err
}
left = &LogicalExpression{Left: left, Operator: "OR", Right: right}
}
return left, nil
}
func (p *QueryParser) parseAndExpression() (Expression, error) {
left, err := p.parseNotExpression()
if err != nil {
return nil, err
}
for p.pos < len(p.tokens) && strings.ToUpper(p.tokens[p.pos]) == "AND" {
p.pos++ // 跳过 AND
right, err := p.parseNotExpression()
if err != nil {
return nil, err
}
left = &LogicalExpression{Left: left, Operator: "AND", Right: right}
}
return left, nil
}
func (p *QueryParser) parseNotExpression() (Expression, error) {
if p.pos < len(p.tokens) && strings.ToUpper(p.tokens[p.pos]) == "NOT" {
p.pos++ // 跳过 NOT
expr, err := p.parseComparisonExpression()
if err != nil {
return nil, err
}
return &NotExpression{Expression: expr}, nil
}
return p.parseComparisonExpression()
}
func (p *QueryParser) parseComparisonExpression() (Expression, error) {
left, err := p.parsePrimaryExpression()
if err != nil {
return nil, err
}
if p.pos < len(p.tokens) {
token := p.tokens[p.pos]
if isComparisonOperator(token) {
p.pos++
right, err := p.parsePrimaryExpression()
if err != nil {
return nil, err
}
return &ComparisonExpression{Left: left, Operator: token, Right: right}, nil
}
}
return left, nil
}
func (p *QueryParser) parsePrimaryExpression() (Expression, error) {
if p.pos >= len(p.tokens) {
return nil, fmt.Errorf("意外的查询结束")
}
token := p.tokens[p.pos]
p.pos++
// 处理括号
if token == "(" {
expr, err := p.parseOrExpression()
if err != nil {
return nil, err
}
if p.pos >= len(p.tokens) || p.tokens[p.pos] != ")" {
return nil, fmt.Errorf("缺少右括号")
}
p.pos++ // 跳过 )
return expr, nil
}
// 处理字符串字面量
if (strings.HasPrefix(token, "\"") && strings.HasSuffix(token, "\"")) ||
(strings.HasPrefix(token, "'") && strings.HasSuffix(token, "'")) {
value := token[1 : len(token)-1] // 移除引号
return &LiteralExpression{Value: value}, nil
}
// 处理数字字面量
if num, err := strconv.ParseFloat(token, 64); err == nil {
return &LiteralExpression{Value: num}, nil
}
// 处理布尔字面量
if strings.ToLower(token) == "true" {
return &LiteralExpression{Value: true}, nil
}
if strings.ToLower(token) == "false" {
return &LiteralExpression{Value: false}, nil
}
// 处理变量
return &VariableExpression{Name: token}, nil
}
func isComparisonOperator(token string) bool {
operators := []string{"=", "!=", ">", "<", ">=", "<=", "LIKE"}
for _, op := range operators {
if strings.ToUpper(token) == op {
return true
}
}
return false
}
// QueryEngine 查询引擎
type QueryEngine struct {
parser *QueryParser
context *Context
}
// NewQueryEngine 创建查询引擎
func NewQueryEngine() *QueryEngine {
return &QueryEngine{
parser: NewQueryParser(),
context: NewContext(),
}
}
// SetData 设置数据
func (e *QueryEngine) SetData(key string, value interface{}) {
e.context.Set(key, value)
}
// Query 执行查询
func (e *QueryEngine) Query(queryStr string) (interface{}, error) {
fmt.Printf("执行查询: %s\n", queryStr)
expr, err := e.parser.Parse(queryStr)
if err != nil {
return nil, fmt.Errorf("解析错误: %v", err)
}
fmt.Printf("解析结果: %s\n", expr.String())
result, err := expr.Interpret(e.context)
if err != nil {
return nil, fmt.Errorf("执行错误: %v", err)
}
fmt.Printf("查询结果: %v\n\n", result)
return result, nil
}
// ShowData 显示所有数据
func (e *QueryEngine) ShowData() {
fmt.Println("当前数据:")
for key, value := range e.context.Data {
fmt.Printf(" %s = %v\n", key, value)
}
fmt.Println()
}
// 演示函数
func demonstrateInterpreterPattern() {
fmt.Println("=== 解释器模式演示:简单查询语言 ===")
engine := NewQueryEngine()
// 设置测试数据
engine.SetData("name", "张三")
engine.SetData("age", 25)
engine.SetData("salary", 8000.0)
engine.SetData("department", "技术部")
engine.SetData("isActive", true)
engine.SetData("email", "zhangsan@company.com")
engine.ShowData()
// 基本比较查询
fmt.Println("1. 基本比较查询")
engine.Query("age > 20")
engine.Query("salary >= 8000")
engine.Query("name = '张三'")
engine.Query("department != '销售部'")
// 逻辑组合查询
fmt.Println("2. 逻辑组合查询")
engine.Query("age > 20 AND salary >= 8000")
engine.Query("department = '技术部' OR department = '产品部'")
engine.Query("age > 30 OR salary > 10000")
// 复杂查询
fmt.Println("3. 复杂查询")
engine.Query("(age > 20 AND salary >= 8000) OR department = '管理层'")
engine.Query("NOT (age < 18 OR salary < 5000)")
engine.Query("isActive = true AND (age >= 25 OR salary >= 7000)")
// 模式匹配查询
fmt.Println("4. 模式匹配查询")
engine.Query("email LIKE '*@company.com'")
engine.Query("name LIKE '张*'")
// 更新数据并重新查询
fmt.Println("5. 更新数据后查询")
engine.SetData("age", 30)
engine.SetData("salary", 12000.0)
engine.ShowData()
engine.Query("age > 25 AND salary > 10000")
}
func main() {
demonstrate_interpreter_pattern()
}
13.3.6 解释器模式的优缺点
优点: 1. 易于扩展:可以轻松添加新的语法规则和表达式 2. 语法清晰:每个语法规则对应一个类,结构清晰 3. 易于实现:对于简单的语言,实现相对容易 4. 灵活性高:可以动态改变和扩展语言的语法 5. 复用性好:表达式类可以在不同的上下文中复用
缺点: 1. 性能较差:对于复杂的语法,解释执行效率低 2. 类数量多:每个语法规则都需要一个类,类数量会很多 3. 维护困难:当语法规则复杂时,维护变得困难 4. 内存开销:构建抽象语法树需要大量内存 5. 调试困难:复杂的表达式树难以调试
13.3.7 解释器模式的适用场景
- 简单语言解释:配置文件解析、脚本语言解释
- 规则引擎:业务规则表达式、验证规则
- 查询语言:简单的查询DSL、过滤表达式
- 数学表达式:计算器、公式解析器
- 模板引擎:简单的模板语言解析
- 配置解析:复杂配置文件的解析和处理
13.4 备忘录模式与解释器模式对比
13.4.1 相同点
- 行为型模式:都属于行为型设计模式
- 状态管理:都涉及状态的管理和处理
- 封装性:都提供了良好的封装性
- 扩展性:都支持功能的扩展
13.4.2 不同点
特性 | 备忘录模式 | 解释器模式 |
---|---|---|
主要目的 | 保存和恢复对象状态 | 解释和执行语言表达式 |
核心概念 | 状态快照 | 语法规则 |
应用场景 | 撤销/重做、状态回滚 | 语言解释、规则引擎 |
性能特点 | 内存开销大 | 执行效率低 |
复杂度 | 相对简单 | 可能很复杂 |
扩展方式 | 增加备忘录类型 | 增加表达式类 |
13.4.3 选择指南
选择备忘录模式的情况: - 需要实现撤销/重做功能 - 需要保存对象的历史状态 - 需要实现事务回滚 - 状态相对简单且变化不频繁
选择解释器模式的情况: - 需要解释简单的语言或表达式 - 需要实现规则引擎 - 语法规则相对固定且不太复杂 - 需要动态执行用户定义的规则
13.4.4 组合使用示例
from typing import List, Dict, Any
from abc import ABC, abstractmethod
import json
import copy
# 备忘录模式:保存解释器状态
class InterpreterMemento:
"""解释器备忘录"""
def __init__(self, variables: Dict[str, Any], expression_history: List[str]):
self._variables = copy.deepcopy(variables)
self._expression_history = copy.deepcopy(expression_history)
def get_variables(self) -> Dict[str, Any]:
return copy.deepcopy(self._variables)
def get_expression_history(self) -> List[str]:
return copy.deepcopy(self._expression_history)
# 解释器上下文(发起人)
class InterpreterContext:
"""解释器上下文"""
def __init__(self):
self.variables: Dict[str, Any] = {}
self.expression_history: List[str] = []
def set_variable(self, name: str, value: Any):
"""设置变量"""
self.variables[name] = value
def get_variable(self, name: str) -> Any:
"""获取变量"""
return self.variables.get(name)
def add_expression(self, expression: str):
"""添加表达式到历史"""
self.expression_history.append(expression)
def create_memento(self) -> InterpreterMemento:
"""创建备忘录"""
return InterpreterMemento(self.variables, self.expression_history)
def restore_from_memento(self, memento: InterpreterMemento):
"""从备忘录恢复"""
self.variables = memento.get_variables()
self.expression_history = memento.get_expression_history()
def clear(self):
"""清空状态"""
self.variables.clear()
self.expression_history.clear()
def show_state(self):
"""显示当前状态"""
print(f"变量: {self.variables}")
print(f"表达式历史: {self.expression_history}")
# 备忘录管理器
class InterpreterCaretaker:
"""解释器状态管理器"""
def __init__(self):
self._mementos: List[InterpreterMemento] = []
self._current_index = -1
def save_state(self, context: InterpreterContext):
"""保存状态"""
# 如果当前不在最新状态,删除后续的备忘录
if self._current_index < len(self._mementos) - 1:
self._mementos = self._mementos[:self._current_index + 1]
memento = context.create_memento()
self._mementos.append(memento)
self._current_index += 1
print(f"状态已保存,当前索引: {self._current_index}")
def undo(self, context: InterpreterContext) -> bool:
"""撤销"""
if self._current_index > 0:
self._current_index -= 1
context.restore_from_memento(self._mementos[self._current_index])
print(f"撤销成功,当前索引: {self._current_index}")
return True
else:
print("无法撤销,已到达最初状态")
return False
def redo(self, context: InterpreterContext) -> bool:
"""重做"""
if self._current_index < len(self._mementos) - 1:
self._current_index += 1
context.restore_from_memento(self._mementos[self._current_index])
print(f"重做成功,当前索引: {self._current_index}")
return True
else:
print("无法重做,已到达最新状态")
return False
def show_history(self):
"""显示历史"""
print(f"\n状态历史(共{len(self._mementos)}个状态,当前索引: {self._current_index}):")
for i, memento in enumerate(self._mementos):
marker = " <- 当前" if i == self._current_index else ""
variables = memento.get_variables()
history = memento.get_expression_history()
print(f" {i}: 变量={variables}, 表达式数量={len(history)}{marker}")
# 简单表达式接口
class Expression(ABC):
"""表达式接口"""
@abstractmethod
def interpret(self, context: InterpreterContext) -> Any:
pass
# 赋值表达式
class AssignExpression(Expression):
"""赋值表达式"""
def __init__(self, variable: str, value: Any):
self.variable = variable
self.value = value
def interpret(self, context: InterpreterContext) -> Any:
context.set_variable(self.variable, self.value)
expression_str = f"{self.variable} = {self.value}"
context.add_expression(expression_str)
return self.value
# 变量表达式
class VariableExpression(Expression):
"""变量表达式"""
def __init__(self, variable: str):
self.variable = variable
def interpret(self, context: InterpreterContext) -> Any:
value = context.get_variable(self.variable)
expression_str = f"get {self.variable}"
context.add_expression(expression_str)
return value
# 算术表达式
class ArithmeticExpression(Expression):
"""算术表达式"""
def __init__(self, left_var: str, operator: str, right_var: str, result_var: str):
self.left_var = left_var
self.operator = operator
self.right_var = right_var
self.result_var = result_var
def interpret(self, context: InterpreterContext) -> Any:
left_val = context.get_variable(self.left_var)
right_val = context.get_variable(self.right_var)
if left_val is None or right_val is None:
raise ValueError(f"变量未定义: {self.left_var} 或 {self.right_var}")
if self.operator == "+":
result = left_val + right_val
elif self.operator == "-":
result = left_val - right_val
elif self.operator == "*":
result = left_val * right_val
elif self.operator == "/":
if right_val == 0:
raise ValueError("除零错误")
result = left_val / right_val
else:
raise ValueError(f"不支持的操作符: {self.operator}")
context.set_variable(self.result_var, result)
expression_str = f"{self.result_var} = {self.left_var} {self.operator} {self.right_var}"
context.add_expression(expression_str)
return result
# 带状态管理的解释器
class StatefulInterpreter:
"""带状态管理的解释器"""
def __init__(self):
self.context = InterpreterContext()
self.caretaker = InterpreterCaretaker()
# 保存初始状态
self.caretaker.save_state(self.context)
def execute(self, expression: Expression) -> Any:
"""执行表达式"""
try:
result = expression.interpret(self.context)
# 执行成功后保存状态
self.caretaker.save_state(self.context)
return result
except Exception as e:
print(f"执行错误: {e}")
raise
def undo(self) -> bool:
"""撤销操作"""
return self.caretaker.undo(self.context)
def redo(self) -> bool:
"""重做操作"""
return self.caretaker.redo(self.context)
def show_state(self):
"""显示当前状态"""
print("\n=== 当前解释器状态 ===")
self.context.show_state()
def show_history(self):
"""显示历史"""
self.caretaker.show_history()
def reset(self):
"""重置到初始状态"""
self.context.clear()
self.caretaker = InterpreterCaretaker()
self.caretaker.save_state(self.context)
print("解释器已重置")
# 演示组合使用
def demonstrate_combined_patterns():
print("=== 备忘录模式与解释器模式组合演示 ===")
interpreter = StatefulInterpreter()
print("\n1. 执行一系列表达式")
# 赋值操作
interpreter.execute(AssignExpression("x", 10))
interpreter.show_state()
interpreter.execute(AssignExpression("y", 5))
interpreter.show_state()
# 算术操作
interpreter.execute(ArithmeticExpression("x", "+", "y", "sum"))
interpreter.show_state()
interpreter.execute(ArithmeticExpression("x", "*", "y", "product"))
interpreter.show_state()
interpreter.execute(ArithmeticExpression("sum", "/", "y", "avg"))
interpreter.show_state()
print("\n2. 显示完整历史")
interpreter.show_history()
print("\n3. 撤销操作")
interpreter.undo() # 撤销 avg 计算
interpreter.show_state()
interpreter.undo() # 撤销 product 计算
interpreter.show_state()
print("\n4. 重做操作")
interpreter.redo() # 重做 product 计算
interpreter.show_state()
print("\n5. 继续执行新操作")
interpreter.execute(ArithmeticExpression("product", "-", "sum", "diff"))
interpreter.show_state()
print("\n6. 最终历史状态")
interpreter.show_history()
print("\n7. 重置解释器")
interpreter.reset()
interpreter.show_state()
interpreter.show_history()
if __name__ == "__main__":
demonstrate_combined_patterns()
13.5 高级应用技巧
13.5.1 备忘录模式优化技巧
1. 增量备忘录
class IncrementalMemento:
"""增量备忘录 - 只保存变化的部分"""
def __init__(self, changes: Dict[str, Any], timestamp: float):
self.changes = changes
self.timestamp = timestamp
def apply_changes(self, state: Dict[str, Any]):
"""应用变化"""
state.update(self.changes)
def reverse_changes(self, state: Dict[str, Any], previous_values: Dict[str, Any]):
"""反向应用变化"""
for key in self.changes:
if key in previous_values:
state[key] = previous_values[key]
else:
state.pop(key, None)
2. 压缩备忘录
import pickle
import gzip
class CompressedMemento:
"""压缩备忘录 - 减少内存占用"""
def __init__(self, state: Any):
# 序列化并压缩状态
serialized = pickle.dumps(state)
self._compressed_data = gzip.compress(serialized)
def get_state(self) -> Any:
"""获取解压缩的状态"""
decompressed = gzip.decompress(self._compressed_data)
return pickle.loads(decompressed)
3. 智能备忘录管理
class SmartCaretaker:
"""智能备忘录管理器"""
def __init__(self, max_mementos: int = 50, auto_cleanup: bool = True):
self.max_mementos = max_mementos
self.auto_cleanup = auto_cleanup
self._mementos = []
self._current_index = -1
def save_state(self, originator):
"""智能保存状态"""
# 自动清理旧的备忘录
if self.auto_cleanup and len(self._mementos) >= self.max_mementos:
self._cleanup_old_mementos()
# 保存新状态
memento = originator.create_memento()
self._mementos.append(memento)
self._current_index = len(self._mementos) - 1
def _cleanup_old_mementos(self):
"""清理旧的备忘录"""
# 保留最近的一半备忘录
keep_count = self.max_mementos // 2
self._mementos = self._mementos[-keep_count:]
self._current_index = len(self._mementos) - 1
13.5.2 解释器模式优化技巧
1. 表达式缓存
from functools import lru_cache
class CachedExpression(Expression):
"""带缓存的表达式"""
def __init__(self, expression_str: str):
self.expression_str = expression_str
self._parsed_expression = None
@lru_cache(maxsize=128)
def _parse_expression(self, expr_str: str):
"""缓存解析结果"""
# 解析表达式的逻辑
return self._do_parse(expr_str)
def interpret(self, context):
if self._parsed_expression is None:
self._parsed_expression = self._parse_expression(self.expression_str)
return self._parsed_expression.interpret(context)
2. 延迟求值
class LazyExpression(Expression):
"""延迟求值表达式"""
def __init__(self, expression_factory):
self.expression_factory = expression_factory
self._expression = None
self._evaluated = False
self._result = None
def interpret(self, context):
if not self._evaluated:
if self._expression is None:
self._expression = self.expression_factory()
self._result = self._expression.interpret(context)
self._evaluated = True
return self._result
3. 表达式优化器
class ExpressionOptimizer:
"""表达式优化器"""
def optimize(self, expression: Expression) -> Expression:
"""优化表达式"""
# 常量折叠
expression = self._constant_folding(expression)
# 死代码消除
expression = self._dead_code_elimination(expression)
# 公共子表达式消除
expression = self._common_subexpression_elimination(expression)
return expression
def _constant_folding(self, expression: Expression) -> Expression:
"""常量折叠优化"""
# 将常量表达式预先计算
pass
def _dead_code_elimination(self, expression: Expression) -> Expression:
"""死代码消除"""
# 移除不会被执行的代码
pass
def _common_subexpression_elimination(self, expression: Expression) -> Expression:
"""公共子表达式消除"""
# 提取公共子表达式
pass
13.5.3 内存和性能优化
1. 对象池模式
class ExpressionPool:
"""表达式对象池"""
def __init__(self):
self._pools = {}
def get_expression(self, expr_type: type, *args, **kwargs):
"""从池中获取表达式对象"""
pool_key = (expr_type, args, tuple(sorted(kwargs.items())))
if pool_key not in self._pools:
self._pools[pool_key] = []
pool = self._pools[pool_key]
if pool:
return pool.pop()
else:
return expr_type(*args, **kwargs)
def return_expression(self, expression: Expression, expr_type: type, *args, **kwargs):
"""将表达式对象返回到池中"""
pool_key = (expr_type, args, tuple(sorted(kwargs.items())))
if pool_key not in self._pools:
self._pools[pool_key] = []
# 重置表达式状态
expression.reset() if hasattr(expression, 'reset') else None
self._pools[pool_key].append(expression)
2. 弱引用管理
import weakref
class WeakReferenceCaretaker:
"""使用弱引用的备忘录管理器"""
def __init__(self):
self._mementos = []
self._weak_refs = []
def save_state(self, originator):
"""保存状态(使用弱引用)"""
memento = originator.create_memento()
# 创建弱引用
weak_ref = weakref.ref(memento, self._cleanup_callback)
self._mementos.append(memento)
self._weak_refs.append(weak_ref)
def _cleanup_callback(self, weak_ref):
"""弱引用清理回调"""
if weak_ref in self._weak_refs:
index = self._weak_refs.index(weak_ref)
self._weak_refs.pop(index)
if index < len(self._mementos):
self._mementos.pop(index)
13.6 实际应用案例
13.6.1 文档编辑器的撤销重做系统
from typing import List, Optional
import time
class DocumentMemento:
"""文档备忘录"""
def __init__(self, content: str, cursor_position: int, timestamp: float):
self._content = content
self._cursor_position = cursor_position
self._timestamp = timestamp
def get_content(self) -> str:
return self._content
def get_cursor_position(self) -> int:
return self._cursor_position
def get_timestamp(self) -> float:
return self._timestamp
class Document:
"""文档类(发起人)"""
def __init__(self):
self.content = ""
self.cursor_position = 0
def insert_text(self, text: str, position: Optional[int] = None):
"""插入文本"""
if position is None:
position = self.cursor_position
self.content = self.content[:position] + text + self.content[position:]
self.cursor_position = position + len(text)
def delete_text(self, start: int, end: int):
"""删除文本"""
self.content = self.content[:start] + self.content[end:]
self.cursor_position = start
def replace_text(self, start: int, end: int, new_text: str):
"""替换文本"""
self.content = self.content[:start] + new_text + self.content[end:]
self.cursor_position = start + len(new_text)
def set_cursor_position(self, position: int):
"""设置光标位置"""
self.cursor_position = max(0, min(position, len(self.content)))
def create_memento(self) -> DocumentMemento:
"""创建备忘录"""
return DocumentMemento(self.content, self.cursor_position, time.time())
def restore_from_memento(self, memento: DocumentMemento):
"""从备忘录恢复"""
self.content = memento.get_content()
self.cursor_position = memento.get_cursor_position()
def get_info(self) -> str:
"""获取文档信息"""
return f"内容长度: {len(self.content)}, 光标位置: {self.cursor_position}"
class DocumentEditor:
"""文档编辑器"""
def __init__(self):
self.document = Document()
self._history: List[DocumentMemento] = []
self._current_index = -1
self._max_history = 100
# 保存初始状态
self._save_state()
def _save_state(self):
"""保存当前状态"""
# 如果当前不在最新状态,删除后续历史
if self._current_index < len(self._history) - 1:
self._history = self._history[:self._current_index + 1]
# 添加新状态
memento = self.document.create_memento()
self._history.append(memento)
# 限制历史记录数量
if len(self._history) > self._max_history:
self._history.pop(0)
else:
self._current_index += 1
def insert_text(self, text: str, position: Optional[int] = None):
"""插入文本"""
self.document.insert_text(text, position)
self._save_state()
print(f"插入文本: '{text}' -> {self.document.get_info()}")
def delete_text(self, start: int, end: int):
"""删除文本"""
deleted_text = self.document.content[start:end]
self.document.delete_text(start, end)
self._save_state()
print(f"删除文本: '{deleted_text}' -> {self.document.get_info()}")
def replace_text(self, start: int, end: int, new_text: str):
"""替换文本"""
old_text = self.document.content[start:end]
self.document.replace_text(start, end, new_text)
self._save_state()
print(f"替换文本: '{old_text}' -> '{new_text}' -> {self.document.get_info()}")
def undo(self) -> bool:
"""撤销"""
if self._current_index > 0:
self._current_index -= 1
self.document.restore_from_memento(self._history[self._current_index])
print(f"撤销成功 -> {self.document.get_info()}")
return True
else:
print("无法撤销")
return False
def redo(self) -> bool:
"""重做"""
if self._current_index < len(self._history) - 1:
self._current_index += 1
self.document.restore_from_memento(self._history[self._current_index])
print(f"重做成功 -> {self.document.get_info()}")
return True
else:
print("无法重做")
return False
def show_content(self):
"""显示文档内容"""
content = self.document.content
cursor_pos = self.document.cursor_position
# 在光标位置插入标记
display_content = content[:cursor_pos] + "|" + content[cursor_pos:]
print(f"文档内容: '{display_content}'")
print(f"信息: {self.document.get_info()}")
def show_history(self):
"""显示历史记录"""
print(f"\n历史记录(共{len(self._history)}个状态,当前索引: {self._current_index}):")
for i, memento in enumerate(self._history):
marker = " <- 当前" if i == self._current_index else ""
content_preview = memento.get_content()[:20] + "..." if len(memento.get_content()) > 20 else memento.get_content()
print(f" {i}: '{content_preview}' (长度: {len(memento.get_content())}){marker}")
# 演示文档编辑器
def demonstrate_document_editor():
print("=== 文档编辑器撤销重做系统演示 ===")
editor = DocumentEditor()
print("\n1. 初始状态")
editor.show_content()
print("\n2. 编辑操作")
editor.insert_text("Hello")
editor.show_content()
editor.insert_text(" World")
editor.show_content()
editor.insert_text("!", 5) # 在位置5插入
editor.show_content()
editor.replace_text(6, 11, "Python")
editor.show_content()
print("\n3. 撤销操作")
editor.undo()
editor.show_content()
editor.undo()
editor.show_content()
print("\n4. 重做操作")
editor.redo()
editor.show_content()
print("\n5. 继续编辑")
editor.insert_text(" Programming")
editor.show_content()
print("\n6. 显示完整历史")
editor.show_history()
if __name__ == "__main__":
demonstrate_document_editor()
13.6.2 配置文件解析器
import re
from typing import Dict, Any, Union
# 配置解释器表达式
class ConfigExpression(ABC):
"""配置表达式基类"""
@abstractmethod
def interpret(self, context: Dict[str, Any]) -> Any:
pass
class LiteralExpression(ConfigExpression):
"""字面量表达式"""
def __init__(self, value: Any):
self.value = value
def interpret(self, context: Dict[str, Any]) -> Any:
return self.value
class VariableExpression(ConfigExpression):
"""变量表达式"""
def __init__(self, name: str):
self.name = name
def interpret(self, context: Dict[str, Any]) -> Any:
if self.name in context:
return context[self.name]
else:
raise ValueError(f"未定义的变量: {self.name}")
class InterpolationExpression(ConfigExpression):
"""插值表达式 ${variable}"""
def __init__(self, template: str):
self.template = template
self.variables = re.findall(r'\$\{([^}]+)\}', template)
def interpret(self, context: Dict[str, Any]) -> str:
result = self.template
for var in self.variables:
if var in context:
value = str(context[var])
result = result.replace(f'${{{var}}}', value)
else:
raise ValueError(f"未定义的变量: {var}")
return result
class ConditionalExpression(ConfigExpression):
"""条件表达式 condition ? true_value : false_value"""
def __init__(self, condition: ConfigExpression, true_expr: ConfigExpression, false_expr: ConfigExpression):
self.condition = condition
self.true_expr = true_expr
self.false_expr = false_expr
def interpret(self, context: Dict[str, Any]) -> Any:
condition_result = self.condition.interpret(context)
if self._is_truthy(condition_result):
return self.true_expr.interpret(context)
else:
return self.false_expr.interpret(context)
def _is_truthy(self, value: Any) -> bool:
"""判断值是否为真"""
if isinstance(value, bool):
return value
elif isinstance(value, (int, float)):
return value != 0
elif isinstance(value, str):
return value.lower() not in ['false', '0', '', 'no', 'off']
else:
return bool(value)
class ComparisonExpression(ConfigExpression):
"""比较表达式"""
def __init__(self, left: ConfigExpression, operator: str, right: ConfigExpression):
self.left = left
self.operator = operator
self.right = right
def interpret(self, context: Dict[str, Any]) -> bool:
left_val = self.left.interpret(context)
right_val = self.right.interpret(context)
if self.operator == "==":
return left_val == right_val
elif self.operator == "!=":
return left_val != right_val
elif self.operator == ">":
return left_val > right_val
elif self.operator == "<":
return left_val < right_val
elif self.operator == ">=":
return left_val >= right_val
elif self.operator == "<=":
return left_val <= right_val
else:
raise ValueError(f"不支持的比较操作符: {self.operator}")
class ConfigParser:
"""配置解析器"""
def __init__(self):
self.context: Dict[str, Any] = {}
def set_variable(self, name: str, value: Any):
"""设置变量"""
self.context[name] = value
def parse_value(self, value_str: str) -> ConfigExpression:
"""解析配置值"""
value_str = value_str.strip()
# 检查是否是插值表达式
if '${' in value_str:
return InterpolationExpression(value_str)
# 检查是否是条件表达式
if '?' in value_str and ':' in value_str:
return self._parse_conditional(value_str)
# 检查是否是比较表达式
for op in ['==', '!=', '>=', '<=', '>', '<']:
if op in value_str:
return self._parse_comparison(value_str, op)
# 检查是否是变量引用
if value_str.startswith('$'):
var_name = value_str[1:]
return VariableExpression(var_name)
# 尝试解析为数字
try:
if '.' in value_str:
return LiteralExpression(float(value_str))
else:
return LiteralExpression(int(value_str))
except ValueError:
pass
# 解析为布尔值
if value_str.lower() in ['true', 'yes', 'on']:
return LiteralExpression(True)
elif value_str.lower() in ['false', 'no', 'off']:
return LiteralExpression(False)
# 默认为字符串
return LiteralExpression(value_str)
def _parse_conditional(self, expr_str: str) -> ConditionalExpression:
"""解析条件表达式"""
question_pos = expr_str.find('?')
colon_pos = expr_str.find(':', question_pos)
condition_str = expr_str[:question_pos].strip()
true_str = expr_str[question_pos + 1:colon_pos].strip()
false_str = expr_str[colon_pos + 1:].strip()
condition_expr = self.parse_value(condition_str)
true_expr = self.parse_value(true_str)
false_expr = self.parse_value(false_str)
return ConditionalExpression(condition_expr, true_expr, false_expr)
def _parse_comparison(self, expr_str: str, operator: str) -> ComparisonExpression:
"""解析比较表达式"""
parts = expr_str.split(operator, 1)
left_str = parts[0].strip()
right_str = parts[1].strip()
left_expr = self.parse_value(left_str)
right_expr = self.parse_value(right_str)
return ComparisonExpression(left_expr, operator, right_expr)
def evaluate(self, value_str: str) -> Any:
"""求值配置表达式"""
expression = self.parse_value(value_str)
return expression.interpret(self.context)
def parse_config_file(self, config_content: str) -> Dict[str, Any]:
"""解析配置文件"""
result = {}
for line in config_content.strip().split('\n'):
line = line.strip()
# 跳过注释和空行
if not line or line.startswith('#'):
continue
# 解析键值对
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
try:
# 求值并存储
evaluated_value = self.evaluate(value)
result[key] = evaluated_value
# 同时将其添加到上下文中,供后续引用
self.set_variable(key, evaluated_value)
except Exception as e:
print(f"解析配置项 '{key}' 时出错: {e}")
result[key] = value # 保存原始值
return result
# 演示配置解析器
def demonstrate_config_parser():
print("=== 配置文件解析器演示 ===")
parser = ConfigParser()
# 设置环境变量
parser.set_variable('ENV', 'production')
parser.set_variable('DEBUG', False)
parser.set_variable('PORT', 8080)
# 配置文件内容
config_content = """
# 应用配置
app_name = MyApp
version = 1.0.0
# 环境相关配置
environment = $ENV
debug_mode = $DEBUG
server_port = $PORT
# 数据库配置
db_host = ${ENV} == production ? prod-db.example.com : dev-db.example.com
db_port = ${ENV} == production ? 5432 : 5433
db_name = myapp_${ENV}
# 缓存配置
cache_enabled = ${ENV} == production ? true : false
cache_ttl = $DEBUG == true ? 60 : 3600
# 日志配置
log_level = $DEBUG == true ? DEBUG : INFO
log_file = /var/log/myapp_${ENV}.log
# 特性开关
feature_x_enabled = $version >= 1.0.0
feature_y_enabled = false
"""
print("\n1. 解析配置文件")
config = parser.parse_config_file(config_content)
print("\n2. 解析结果")
for key, value in config.items():
print(f" {key} = {value} ({type(value).__name__})")
print("\n3. 修改环境变量并重新解析")
parser.set_variable('ENV', 'development')
parser.set_variable('DEBUG', True)
config_dev = parser.parse_config_file(config_content)
print("\n4. 开发环境配置")
for key, value in config_dev.items():
print(f" {key} = {value} ({type(value).__name__})")
print("\n5. 单独测试表达式")
test_expressions = [
"${ENV} == production ? 8080 : 3000",
"$DEBUG == true ? verbose : normal",
"app_${ENV}_v${version}",
"$PORT > 8000"
]
for expr in test_expressions:
try:
result = parser.evaluate(expr)
print(f" '{expr}' -> {result} ({type(result).__name__})")
except Exception as e:
print(f" '{expr}' -> 错误: {e}")
if __name__ == "__main__":
demonstrate_config_parser()
13.7 本章总结
13.7.1 核心概念回顾
备忘录模式: - 目的:在不破坏封装性的前提下,捕获和恢复对象的内部状态 - 核心组件:发起人(Originator)、备忘录(Memento)、管理者(Caretaker) - 关键特性:状态保存、状态恢复、封装保护
解释器模式: - 目的:定义语言的文法表示,并提供解释器来处理语言中的句子 - 核心组件:抽象表达式、终结符表达式、非终结符表达式、上下文 - 关键特性:语法解析、表达式求值、语言扩展
13.7.2 最佳实践
备忘录模式最佳实践:
- 合理控制备忘录的数量,避免内存溢出
- 使用增量备忘录减少内存占用
- 实现智能清理机制
- 考虑使用压缩技术
- 提供批量操作的撤销功能
解释器模式最佳实践:
- 保持语法简单,避免过度复杂
- 使用缓存优化重复解析
- 实现表达式优化器
- 提供良好的错误处理
- 考虑使用访问者模式进行语法树遍历
13.7.3 实际应用建议
选择合适的场景:
- 备忘录模式适用于需要撤销/重做功能的应用
- 解释器模式适用于需要处理简单DSL的场景
性能考虑:
- 备忘录模式要注意内存管理
- 解释器模式要注意执行效率
扩展性设计:
- 预留扩展接口
- 使用组合模式增强灵活性
13.7.4 注意事项
内存管理:
- 及时清理不需要的备忘录
- 使用弱引用避免内存泄漏
- 实现内存使用监控
性能优化:
- 使用对象池减少对象创建开销
- 实现延迟加载和缓存机制
- 避免深度递归导致的栈溢出
错误处理:
- 提供详细的错误信息
- 实现优雅的降级机制
- 添加调试和日志功能
13.8 练习题
13.8.1 基础练习
备忘录模式练习:
- 实现一个简单的画图程序,支持撤销/重做功能
- 为游戏角色实现存档/读档系统
- 创建一个支持历史记录的计算器
解释器模式练习:
- 实现一个简单的布尔表达式解释器
- 创建一个基本的SQL WHERE子句解释器
- 设计一个配置文件表达式解析器
13.8.2 进阶练习
组合应用:
- 结合备忘录模式和解释器模式,实现一个支持撤销的脚本执行器
- 创建一个可视化的表达式编辑器,支持拖拽构建和撤销操作
- 实现一个支持版本控制的配置管理系统
性能优化:
- 为备忘录模式实现增量保存和压缩功能
- 为解释器模式添加表达式缓存和优化功能
- 实现内存使用监控和自动清理机制
13.8.3 思考题
- 如何在分布式系统中实现备忘录模式?
- 解释器模式与编译器设计有什么关系?
- 如何结合其他设计模式来增强备忘录模式和解释器模式的功能?
- 在什么情况下应该选择解释器模式而不是策略模式?
- 如何设计一个支持并发访问的备忘录系统?
下一章预告: 在下一章中,我们将学习模板方法模式与工厂方法模式的高级应用,探讨如何通过这两种模式实现更灵活的算法框架和对象创建机制,以及它们在实际项目中的最佳实践。