设计模式-16备忘录模式Memento Pattern

Rijndael密码算法 一 什么是Rijndael Rijndael是由比利时密码学家设计的分组密码算法,于2000年被选为新一代的标准密码算法——AES。今后会有越来越多的密码软件支持这种算法。 Rijndael的分组长度和密钥长度可以分别以32比特为单位在128比特和256比特的范围内进行选择。不过在AES的规格中,分组长度固定为128比特,密钥长度只有128、192和256比特三种。 二 Rijndael的加... 阅读详情

备忘录模式 (Memento Pattern)

概述 (Overview)

备忘录模式是一种行为型设计模式,它允许在不暴露对象实现细节的情况下捕获对象的内部状态,并在以后将该对象恢复到原先保存的状态。

Memento Pattern is a behavioral design pattern that lets you save and restore the previous state of an object without revealing the details of its implementation.

意图 (Intent)

在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。

Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.

适用场景 (When to Use)

  • 当需要保存和恢复对象的状态,而又不破坏对象的封装性时
  • 当需要实现撤销/重做功能时
  • 当需要保存对象的历史状态以便回滚时
  • 当需要创建对象状态的检查点时
  • 当需要实现事务回滚机制时
  • 当需要保存对象的多个状态快照时

结构 (Structure)

基础备忘录模式结构图 (Basic Memento Pattern Structure)

creates
stores
uses
uses
Memento
-state: Object
+getState()
Originator
-state: Object
+createMemento()
+setMemento(memento: Memento)
+setState(state: Object)
+getState()
Caretaker
-mementos: List
+addMemento(memento: Memento)
+getMemento(index: int)
Client
+saveState()
+restoreState()

实现方式 (Implementation Approaches)

1. 经典备忘录模式 (Classic Memento Pattern)

// 备忘录接口 - Memento Interface
public interface Memento {
    // 备忘录接口可以为空,也可以定义一些获取状态的方法
}

// 具体备忘录 - Concrete Memento
public class TextEditorMemento implements Memento {
    private final String content;
    private final int cursorPosition;
    private final Date timestamp;
    
    public TextEditorMemento(String content, int cursorPosition) {
        this.content = content;
        this.cursorPosition = cursorPosition;
        this.timestamp = new Date();
    }
    
    public String getContent() {
        return content;
    }
    
    public int getCursorPosition() {
        return cursorPosition;
    }
    
    public Date getTimestamp() {
        return timestamp;
    }
    
    @Override
    public String toString() {
        return String.format("Memento{content='%s...', cursor=%d, time=%s}", 
                           content.substring(0, Math.min(content.length(), 20)), 
                           cursorPosition, timestamp);
    }
}

// 原发器 - Originator
public class TextEditor {
    private String content;
    private int cursorPosition;
    
    public TextEditor() {
        this.content = "";
        this.cursorPosition = 0;
    }
    
    public void write(String text) {
        String beforeCursor = content.substring(0, cursorPosition);
        String afterCursor = content.substring(cursorPosition);
        content = beforeCursor + text + afterCursor;
        cursorPosition += text.length();
        System.out.println("写入文本: '" + text + "'");
    }
    
    public void delete(int length) {
        if (length <= 0 || cursorPosition < length) return;
        
        String beforeCursor = content.substring(0, cursorPosition - length);
        String afterCursor = content.substring(cursorPosition);
        content = beforeCursor + afterCursor;
        cursorPosition -= length;
        System.out.println("删除 " + length + " 个字符");
    }
    
    public void moveCursor(int position) {
        if (position >= 0 && position <= content.length()) {
            cursorPosition = position;
            System.out.println("移动光标到位置: " + position);
        }
    }
    
    public void moveCursorToEnd() {
        cursorPosition = content.length();
        System.out.println("移动光标到末尾");
    }
    
    // 创建备忘录
    public TextEditorMemento createMemento() {
        System.out.println("创建备忘录: " + content.substring(0, Math.min(content.length(), 10)) + "...");
        return new TextEditorMemento(content, cursorPosition);
    }
    
    // 从备忘录恢复状态
    public void restoreFromMemento(TextEditorMemento memento) {
        this.content = memento.getContent();
        this.cursorPosition = memento.getCursorPosition();
        System.out.println("从备忘录恢复状态");
    }
    
    // 获取当前状态
    public String getContent() {
        return content;
    }
    
    public int getCursorPosition() {
        return cursorPosition;
    }
    
    public void display() {
        System.out.println("当前内容: \"" + content + "\"");
        System.out.println("光标位置: " + cursorPosition);
        if (cursorPosition > 0) {
            System.out.println("光标指示: " + " ".repeat(cursorPosition - 1) + "^");
        }
    }
}

// 管理者 - Caretaker
public class TextEditorHistory {
    private final Stack<TextEditorMemento> history;
    private final int maxSize;
    
    public TextEditorHistory() {
        this(50); // 默认最多保存50个状态
    }
    
    public TextEditorHistory(int maxSize) {
        this.history = new Stack<>();
        this.maxSize = maxSize;
    }
    
    public void save(TextEditorMemento memento) {
        if (history.size() >= maxSize) {
            history.remove(0); // 移除最旧的状态
        }
        history.push(memento);
        System.out.println("保存备忘录到历史记录");
    }
    
    public TextEditorMemento undo() {
        if (history.isEmpty()) {
            throw new IllegalStateException("没有可撤销的状态");
        }
        TextEditorMemento memento = history.pop();
        System.out.println("撤销到备忘录: " + memento);
        return memento;
    }
    
    public boolean canUndo() {
        return !history.isEmpty();
    }
    
    public void clear() {
        history.clear();
        System.out.println("清空历史记录");
    }
    
    public int getHistorySize() {
        return history.size();
    }
    
    public TextEditorMemento getMemento(int index) {
        if (index < 0 || index >= history.size()) {
            throw new IndexOutOfBoundsException("索引超出范围");
        }
        return history.get(index);
    }
}

// 客户端使用 - Client Usage
public class TextEditorDemo {
    public static void main(String[] args) {
        System.out.println("=== 文本编辑器备忘录模式演示 ===");
        
        TextEditor editor = new TextEditor();
        TextEditorHistory history = new TextEditorHistory();
        
        System.out.println("\n--- 初始状态 ---");
        editor.display();
        
        // 编辑文本并保存状态
        System.out.println("\n--- 编辑文本 ---");
        editor.write("Hello ");
        history.save(editor.createMemento());
        
        editor.write("World");
        history.save(editor.createMemento());
        
        editor.write("!");
        history.save(editor.createMemento());
        
        editor.display();
        
        // 继续编辑
        System.out.println("\n--- 继续编辑 ---");
        editor.write(" Welcome");
        editor.display();
        
        // 撤销操作
        System.out.println("\n--- 撤销操作 ---");
        if (history.canUndo()) {
            editor.restoreFromMemento(history.undo());
            editor.display();
        }
        
        if (history.canUndo()) {
            editor.restoreFromMemento(history.undo());
            editor.display();
        }
        
        // 再次编辑
        System.out.println("\n--- 再次编辑 ---");
        editor.write(" Java");
        history.save(editor.createMemento());
        editor.display();
        
        System.out.println("\n历史记录大小: " + history.getHistorySize());
    }
}

2. 宽接口备忘录模式 (Wide Interface Memento Pattern)

// 宽接口备忘录 - Wide Interface Memento
public class GameMemento {
    private final int level;
    private final int score;
    private final int health;
    private final double x;
    private final double y;
    private final String weapon;
    private final List<String> inventory;
    private final Date timestamp;
    
    public GameMemento(int level, int score, int health, double x, double y, 
                      String weapon, List<String> inventory) {
        this.level = level;
        this.score = score;
        this.health = health;
        this.x = x;
        this.y = y;
        this.weapon = weapon;
        this.inventory = new ArrayList<>(inventory);
        this.timestamp = new Date();
    }
    
    // 宽接口:提供所有状态的访问方法
    public int getLevel() { return level; }
    public int getScore() { return score; }
    public int getHealth() { return health; }
    public double getX() { return x; }
    public double getY() { return y; }
    public String getWeapon() { return weapon; }
    public List<String> getInventory() { return new ArrayList<>(inventory); }
    public Date getTimestamp() { return timestamp; }
    
    @Override
    public String toString() {
        return String.format("GameMemento{level=%d, score=%d, health=%d, pos=(%.1f,%.1f), weapon='%s', items=%d}", 
                           level, score, health, x, y, weapon, inventory.size());
    }
}

// 游戏角色 - Game Character (Originator)
public class GameCharacter {
    private int level;
    private int score;
    private int health;
    private double x;
    private double y;
    private String weapon;
    private List<String> inventory;
    
    public GameCharacter(String name) {
        this.level = 1;
        this.score = 0;
        this.health = 100;
        this.x = 0.0;
        this.y = 0.0;
        this.weapon = "空手";
        this.inventory = new ArrayList<>();
        this.inventory.add("地图");
    }
    
    public void move(double dx, double dy) {
        this.x += dx;
        this.y += dy;
        System.out.printf("移动到 (%.1f, %.1f)%n", x, y);
    }
    
    public void attack() {
        if (health > 0) {
            System.out.println("使用 " + weapon + " 攻击!");
            score += 10;
        } else {
            System.out.println("生命值不足,无法攻击");
        }
    }
    
    public void takeDamage(int damage) {
        health = Math.max(0, health - damage);
        System.out.println("受到 " + damage + " 点伤害,当前生命值: " + health);
    }
    
    public void pickUpItem(String item) {
        inventory.add(item);
        System.out.println("拾取物品: " + item);
    }
    
    public void changeWeapon(String newWeapon) {
        String oldWeapon = weapon;
        weapon = newWeapon;
        System.out.println("更换武器: " + oldWeapon + " -> " + newWeapon);
    }
    
    public void levelUp() {
        level++;
        health = 100; // 升级后恢复生命值
        System.out.println("升级!当前等级: " + level);
    }
    
    // 创建备忘录
    public GameMemento createSavePoint() {
        System.out.println("创建游戏存档点...");
        return new GameMemento(level, score, health, x, y, weapon, inventory);
    }
    
    // 从备忘录恢复
    public void restoreFromSavePoint(GameMemento memento) {
        this.level = memento.getLevel();
        this.score = memento.getScore();
        this.health = memento.getHealth();
        this.x = memento.getX();
        this.y = memento.getY();
        this.weapon = memento.getWeapon();
        this.inventory = new ArrayList<>(memento.getInventory());
        System.out.println("从存档点恢复游戏状态");
    }
    
    public void displayStatus() {
        System.out.println("\n=== 角色状态 ===");
        System.out.println("等级: " + level);
        System.out.println("分数: " + score);
        System.out.println("生命值: " + health);
        System.out.println("位置: (" + x + ", " + y + ")");
        System.out.println("武器: " + weapon);
        System.out.println("背包: " + inventory);
    }
}

// 游戏存档管理器 - Game Save Manager (Caretaker)
public class GameSaveManager {
    private final Map<String, GameMemento> saveSlots;
    private final int maxSlots;
    private String autoSaveSlot;
    
    public GameSaveManager(int maxSlots) {
        this.saveSlots = new LinkedHashMap<>();
        this.maxSlots = maxSlots;
        this.autoSaveSlot = "auto_save";
    }
    
    public void saveGame(String slotName, GameMemento memento) {
        if (saveSlots.size() >= maxSlots && !saveSlots.containsKey(slotName)) {
            // 移除最旧的存档
            String oldestSlot = saveSlots.keySet().iterator().next();
            saveSlots.remove(oldestSlot);
            System.out.println("存档槽已满,移除最旧的存档: " + oldestSlot);
        }
        
        saveSlots.put(slotName, memento);
        System.out.println("游戏已保存到槽位: " + slotName);
    }
    
    public GameMemento loadGame(String slotName) {
        GameMemento memento = saveSlots.get(slotName);
        if (memento == null) {
            throw new IllegalArgumentException("存档槽不存在: " + slotName);
        }
        System.out.println("从槽位加载游戏: " + slotName);
        return memento;
    }
    
    public void autoSave(GameMemento memento) {
        saveGame(autoSaveSlot, memento);
        System.out.println("自动保存完成");
    }
    
    public GameMemento loadAutoSave() {
        return loadGame(autoSaveSlot);
    }
    
    public boolean hasAutoSave() {
        return saveSlots.containsKey(autoSaveSlot);
    }
    
    public void deleteSave(String slotName) {
        if (saveSlots.remove(slotName) != null) {
            System.out.println("删除存档: " + slotName);
        }
    }
    
    public List<String> getSaveSlots() {
        return new ArrayList<>(saveSlots.keySet());
    }
    
    public void displaySaveInfo() {
        System.out.println("\n=== 存档信息 ===");
        if (saveSlots.isEmpty()) {
            System.out.println("没有存档");
            return;
        }
        
        for (Map.Entry<String, GameMemento> entry : saveSlots.entrySet()) {
            System.out.println("槽位: " + entry.getKey() + " -> " + entry.getValue());
        }
    }
}

// 客户端使用 - Client Usage
public class GameSaveDemo {
    public static void main(String[] args) {
        System.out.println("=== 游戏存档备忘录模式演示 ===");
        
        GameCharacter character = new GameCharacter("勇者");
        GameSaveManager saveManager = new GameSaveManager(5);
        
        // 初始状态
        character.displayStatus();
        
        // 游戏过程
        System.out.println("\n--- 开始游戏 ---");
        character.move(10, 5);
        character.pickUpItem("生命药水");
        character.attack();
        saveManager.saveGame("checkpoint_1", character.createSavePoint());
        
        character.move(20, 10);
        character.takeDamage(30);
        character.pickUpItem("铁剑");
        character.changeWeapon("铁剑");
        character.attack();
        saveManager.saveGame("checkpoint_2", character.createSavePoint());
        
        character.move(30, 15);
        character.pickUpItem("魔法卷轴");
        character.attack();
        character.levelUp();
        saveManager.autoSave(character.createSavePoint());
        
        // 遭遇失败
        System.out.println("\n--- 遭遇强敌,角色死亡 ---");
        character.takeDamage(80);
        character.displayStatus();
        
        // 从存档恢复
        System.out.println("\n--- 从存档点恢复 ---");
        character.restoreFromSavePoint(saveManager.loadGame("checkpoint_2"));
        character.displayStatus();
        
        // 继续游戏
        System.out.println("\n--- 继续游戏 ---");
        character.move(25, 12);
        character.pickUpItem("盾牌");
        character.attack();
        saveManager.saveGame("checkpoint_3", character.createSavePoint());
        
        // 显示存档信息
        saveManager.displaySaveInfo();
        
        System.out.println("\n游戏继续...");
    }
}

3. 增量备忘录模式 (Incremental Memento Pattern)

// 增量状态变化 - Incremental State Change
public class StateChange {
    private final String propertyName;
    private final Object oldValue;
    private final Object newValue;
    private final Date timestamp;
    
    public StateChange(String propertyName, Object oldValue, Object newValue) {
        this.propertyName = propertyName;
        this.oldValue = oldValue;
        this.newValue = newValue;
        this.timestamp = new Date();
    }
    
    public String getPropertyName() { return propertyName; }
    public Object getOldValue() { return oldValue; }
    public Object getNewValue() { return newValue; }
    public Date getTimestamp() { return timestamp; }
    
    @Override
    public String toString() {
        return String.format("Change{%s: %s -> %s}", propertyName, oldValue, newValue);
    }
}

// 增量备忘录 - Incremental Memento
public class DocumentMemento {
    private final List<StateChange> changes;
    private final Date timestamp;
    
    public DocumentMemento() {
        this.changes = new ArrayList<>();
        this.timestamp = new Date();
    }
    
    public void addChange(StateChange change) {
        changes.add(change);
    }
    
    public List<StateChange> getChanges() {
        return new ArrayList<>(changes);
    }
    
    public Date getTimestamp() {
        return timestamp;
    }
    
    public boolean isEmpty() {
        return changes.isEmpty();
    }
    
    @Override
    public String toString() {
        return String.format("DocumentMemento{changes=%d, time=%s}", changes.size(), timestamp);
    }
}

// 文档编辑器 - Document Editor (Originator)
public class DocumentEditor {
    private String title;
    private String content;
    private String font;
    private int fontSize;
    private String color;
    private boolean bold;
    private boolean italic;
    private boolean underline;
    
    public DocumentEditor() {
        this.title = "Untitled";
        this.content = "";
        this.font = "Arial";
        this.fontSize = 12;
        this.color = "Black";
        this.bold = false;
        this.italic = false;
        this.underline = false;
    }
    
    public void setTitle(String title) {
        String oldTitle = this.title;
        this.title = title;
        System.out.println("设置标题: " + title);
        // 这里可以记录状态变化
    }
    
    public void setContent(String content) {
        String oldContent = this.content;
        this.content = content;
        System.out.println("设置内容: " + content.substring(0, Math.min(content.length(), 20)) + "...");
        // 这里可以记录状态变化
    }
    
    public void setFont(String font) {
        String oldFont = this.font;
        this.font = font;
        System.out.println("设置字体: " + font);
        // 这里可以记录状态变化
    }
    
    public void setFontSize(int fontSize) {
        int oldSize = this.fontSize;
        this.fontSize = fontSize;
        System.out.println("设置字体大小: " + fontSize);
        // 这里可以记录状态变化
    }
    
    public void setColor(String color) {
        String oldColor = this.color;
        this.color = color;
        System.out.println("设置颜色: " + color);
        // 这里可以记录状态变化
    }
    
    public void toggleBold() {
        this.bold = !bold;
        System.out.println("切换粗体: " + bold);
        // 这里可以记录状态变化
    }
    
    public void toggleItalic() {
        this.italic = !italic;
        System.out.println("切换斜体: " + italic);
        // 这里可以记录状态变化
    }
    
    public void toggleUnderline() {
        this.underline = !underline;
        System.out.println("切换下划线: " + underline);
        // 这里可以记录状态变化
    }
    
    // 创建增量备忘录
    public DocumentMemento createIncrementalMemento() {
        DocumentMemento memento = new DocumentMemento();
        // 在实际应用中,这里会记录自上次备忘录以来的所有变化
        memento.addChange(new StateChange("title", null, title));
        memento.addChange(new StateChange("content", null, content));
        memento.addChange(new StateChange("font", null, font));
        memento.addChange(new StateChange("fontSize", null, fontSize));
        memento.addChange(new StateChange("color", null, color));
        memento.addChange(new StateChange("bold", null, bold));
        memento.addChange(new StateChange("italic", null, italic));
        memento.addChange(new StateChange("underline", null, underline));
        
        System.out.println("创建增量备忘录");
        return memento;
    }
    
    // 从增量备忘录恢复
    public void restoreFromIncrementalMemento(DocumentMemento memento) {
        System.out.println("从增量备忘录恢复:");
        for (StateChange change : memento.getChanges()) {
            System.out.println("  " + change);
            // 在实际应用中,这里会根据变化类型恢复相应的状态
        }
        System.out.println("恢复完成");
    }
    
    // 创建完整备忘录(快照)
    public DocumentMemento createFullMemento() {
        return createIncrementalMemento(); // 在实际应用中会有所不同
    }
    
    public void displayDocumentInfo() {
        System.out.println("\n=== 文档信息 ===");
        System.out.println("标题: " + title);
        System.out.println("内容: " + content.substring(0, Math.min(content.length(), 30)) + "...");
        System.out.println("字体: " + font + ", 大小: " + fontSize + ", 颜色: " + color);
        System.out.println("格式: " + (bold ? "粗体" : "") + " " + (italic ? "斜体" : "") + " " + (underline ? "下划线" : ""));
    }
}

// 文档历史管理器 - Document History Manager (Caretaker)
public class DocumentHistoryManager {
    private final Stack<DocumentMemento> undoStack;
    private final Stack<DocumentMemento> redoStack;
    private final int maxUndoLevels;
    
    public DocumentHistoryManager() {
        this(20); // 默认支持20级撤销
    }
    
    public DocumentHistoryManager(int maxUndoLevels) {
        this.undoStack = new Stack<>();
        this.redoStack = new Stack<>();
        this.maxUndoLevels = maxUndoLevels;
    }
    
    public void saveState(DocumentMemento memento) {
        if (undoStack.size() >= maxUndoLevels) {
            undoStack.remove(0); // 移除最旧的状态
        }
        undoStack.push(memento);
        redoStack.clear(); // 保存新状态后清空重做栈
        System.out.println("保存文档状态");
    }
    
    public DocumentMemento undo() {
        if (undoStack.isEmpty()) {
            throw new IllegalStateException("没有可撤销的状态");
        }
        
        DocumentMemento current = undoStack.pop();
        redoStack.push(current);
        
        if (undoStack.isEmpty()) {
            throw new IllegalStateException("已经是最初状态");
        }
        
        DocumentMemento previous = undoStack.peek();
        System.out.println("执行撤销操作");
        return previous;
    }
    
    public DocumentMemento redo() {
        if (redoStack.isEmpty()) {
            throw new IllegalStateException("没有可重做的状态");
        }
        
        DocumentMemento memento = redoStack.pop();
        undoStack.push(memento);
        System.out.println("执行重做操作");
        return memento;
    }
    
    public boolean canUndo() {
        return undoStack.size() > 1; // 至少有一个状态可以撤销到
    }
    
    public boolean canRedo() {
        return !redoStack.isEmpty();
    }
    
    public void clearHistory() {
        undoStack.clear();
        redoStack.clear();
        System.out.println("清空历史记录");
    }
    
    public int getUndoStackSize() {
        return undoStack.size();
    }
    
    public int getRedoStackSize() {
        return redoStack.size();
    }
}

// 客户端使用 - Client Usage
public class IncrementalMementoDemo {
    public static void main(String[] args) {
        System.out.println("=== 增量备忘录模式演示 ===");
        
        DocumentEditor editor = new DocumentEditor();
        DocumentHistoryManager history = new DocumentHistoryManager();
        
        // 初始状态
        editor.displayDocumentInfo();
        history.saveState(editor.createFullMemento());
        
        // 编辑文档
        System.out.println("\n--- 编辑文档 ---");
        editor.setTitle("我的文档");
        editor.setContent("这是一个测试文档,用于演示备忘录模式。");
        editor.setFont("Times New Roman");
        editor.setFontSize(14);
        editor.toggleBold();
        history.saveState(editor.createIncrementalMemento());
        
        // 继续编辑
        System.out.println("\n--- 继续编辑 ---");
        editor.setColor("Blue");
        editor.toggleItalic();
        editor.setContent("这是一个测试文档,用于演示备忘录模式。现在内容更丰富了。");
        history.saveState(editor.createIncrementalMemento());
        
        editor.displayDocumentInfo();
        
        // 撤销操作
        System.out.println("\n--- 撤销操作 ---");
        if (history.canUndo()) {
            editor.restoreFromIncrementalMemento(history.undo());
            editor.displayDocumentInfo();
        }
        
        // 重做操作
        System.out.println("\n--- 重做操作 ---");
        if (history.canRedo()) {
            editor.restoreFromIncrementalMemento(history.redo());
            editor.displayDocumentInfo();
        }
        
        System.out.println("\n撤销栈大小: " + history.getUndoStackSize());
        System.out.println("重做栈大小: " + history.getRedoStackSize());
    }
}

框架源码中的应用 (Framework Applications)

1. Java Serializable - 序列化机制

// Java序列化中的备忘录模式应用
// Java Serialization Memento Pattern Application

// 可序列化的游戏状态 - Serializable Game State
public class GameState implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private String playerName;
    private int level;
    private int score;
    private double playerX;
    private double playerY;
    private List<String> inventory;
    private Map<String, Integer> achievements;
    
    public GameState(String playerName) {
        this.playerName = playerName;
        this.level = 1;
        this.score = 0;
        this.playerX = 0.0;
        this.playerY = 0.0;
        this.inventory = new ArrayList<>();
        this.achievements = new HashMap<>();
    }
    
    // 游戏操作方法
    public void movePlayer(double dx, double dy) {
        playerX += dx;
        playerY += dy;
        System.out.printf("玩家移动到 (%.1f, %.1f)%n", playerX, playerY);
    }
    
    public void addScore(int points) {
        score += points;
        System.out.println("获得分数: " + points + ", 总分数: " + score);
    }
    
    public void levelUp() {
        level++;
        System.out.println("升级!当前等级: " + level);
    }
    
    public void addItem(String item) {
        inventory.add(item);
        System.out.println("获得物品: " + item);
    }
    
    public void unlockAchievement(String achievement, int points) {
        achievements.put(achievement, points);
        addScore(points);
        System.out.println("解锁成就: " + achievement);
    }
    
    // 创建备忘录(序列化)
    public byte[] createMemento() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(this);
        oos.close();
        System.out.println("创建游戏状态备忘录");
        return baos.toByteArray();
    }
    
    // 从备忘录恢复(反序列化)
    public static GameState restoreFromMemento(byte[] mementoData) throws IOException, ClassNotFoundException {
        ByteArrayInputStream bais = new ByteArrayInputStream(mementoData);
        ObjectInputStream ois = new ObjectInputStream(bais);
        GameState state = (GameState) ois.readObject();
        ois.close();
        System.out.println("从备忘录恢复游戏状态");
        return state;
    }
    
    public void displayStatus() {
        System.out.println("\n=== 游戏状态 ===");
        System.out.println("玩家: " + playerName);
        System.out.println("等级: " + level);
        System.out.println("分数: " + score);
        System.out.println("位置: (" + playerX + ", " + playerY + ")");
        System.out.println("背包: " + inventory);
        System.out.println("成就: " + achievements);
    }
    
    @Override
    public String toString() {
        return String.format("GameState{%s, Lv.%d, Score:%d, (%.1f,%.1f), Items:%d}", 
                           playerName, level, score, playerX, playerY, inventory.size());
    }
}

// 游戏存档管理器 - Game Save Manager (Caretaker)
public class SerializableGameSaveManager {
    private final Map<String, byte[]> saveSlots;
    private final String saveDirectory;
    
    public SerializableGameSaveManager(String saveDirectory) {
        this.saveSlots = new LinkedHashMap<>();
        this.saveDirectory = saveDirectory;
        ensureSaveDirectoryExists();
    }
    
    private void ensureSaveDirectoryExists() {
        File dir = new File(saveDirectory);
        if (!dir.exists()) {
            dir.mkdirs();
        }
    }
    
    public void saveGame(String slotName, GameState gameState) throws IOException {
        byte[] mementoData = gameState.createMemento();
        saveSlots.put(slotName, mementoData);
        
        // 同时保存到文件
        String fileName = saveDirectory + File.separator + slotName + ".sav";
        try (FileOutputStream fos = new FileOutputStream(fileName)) {
            fos.write(mementoData);
        }
        
        System.out.println("游戏已保存到槽位: " + slotName);
    }
    
    public GameState loadGame(String slotName) throws IOException, ClassNotFoundException {
        byte[] mementoData = saveSlots.get(slotName);
        if (mementoData == null) {
            // 尝试从文件加载
            String fileName = saveDirectory + File.separator + slotName + ".sav";
            File file = new File(fileName);
            if (file.exists()) {
                mementoData = Files.readAllBytes(file.toPath());
                saveSlots.put(slotName, mementoData);
            } else {
                throw new IllegalArgumentException("存档不存在: " + slotName);
            }
        }
        
        System.out.println("从槽位加载游戏: " + slotName);
        return GameState.restoreFromMemento(mementoData);
    }
    
    public void autoSave(GameState gameState) throws IOException {
        String autoSaveName = "auto_save_" + System.currentTimeMillis();
        saveGame(autoSaveName, gameState);
        System.out.println("自动保存完成: " + autoSaveName);
    }
    
    public List<String> getSaveSlots() {
        return new ArrayList<>(saveSlots.keySet());
    }
    
    public void deleteSave(String slotName) {
        saveSlots.remove(slotName);
        
        // 同时删除文件
        String fileName = saveDirectory + File.separator + slotName + ".sav";
        File file = new File(fileName);
        if (file.exists()) {
            file.delete();
        }
        
        System.out.println("删除存档: " + slotName);
    }
}

// 客户端使用 - Client Usage
public class SerializableMementoDemo {
    public static void main(String[] args) {
        System.out.println("=== Java序列化备忘录模式演示 ===");
        
        try {
            GameState game = new GameState("勇者");
            SerializableGameSaveManager saveManager = new SerializableGameSaveManager("saves");
            
            // 初始状态
            game.displayStatus();
            
            // 游戏过程
            System.out.println("\n--- 开始游戏 ---");
            game.movePlayer(10, 5);
            game.addScore(100);
            game.addItem("生命药水");
            game.unlockAchievement("首次移动", 50);
            saveManager.saveGame("checkpoint_1", game);
            
            game.movePlayer(20, 10);
            game.addScore(200);
            game.levelUp();
            game.addItem("铁剑");
            game.unlockAchievement("首次升级", 100);
            saveManager.saveGame("checkpoint_2", game);
            
            // 创建游戏副本进行实验
            System.out.println("\n--- 创建游戏副本进行实验 ---");
            GameState experimentalGame = GameState.restoreFromMemento(game.createMemento());
            experimentalGame.displayStatus();
            
            // 在副本中进行危险操作
            System.out.println("\n--- 在副本中进行危险操作 ---");
            experimentalGame.movePlayer(100, 50);
            experimentalGame.addScore(500);
            experimentalGame.takeDamage(80);
            experimentalGame.displayStatus();
            
            // 实验失败,恢复原状态
            System.out.println("\n--- 实验失败,恢复原状态 ---");
            game.displayStatus();
            
            // 继续正常游戏
            System.out.println("\n--- 继续正常游戏 ---");
            game.movePlayer(15, 8);
            game.addScore(150);
            saveManager.autoSave(game);
            
            game.displayStatus();
            
            // 显示存档信息
            System.out.println("\n可用存档:");
            saveManager.getSaveSlots().forEach(System.out::println);
            
        } catch (Exception e) {
            System.err.println("游戏存档操作失败: " + e.getMessage());
            e.printStackTrace();
        }
        
        System.out.println("\n=== Java序列化备忘录模式演示完成 ===");
    }
}

2. Spring State Machine - 状态机

// Spring状态机中的备忘录模式应用
// Spring State Machine Memento Pattern Application

// 订单状态枚举 - Order State Enum
public enum OrderState {
    CREATED, PAID, SHIPPED, DELIVERED, CANCELLED
}

// 订单事件枚举 - Order Event Enum
public enum OrderEvent {
    PAY, SHIP, DELIVER, CANCEL
}

// 订单状态机配置 - Order State Machine Configuration
@Configuration
@EnableStateMachine
public class OrderStateMachineConfig extends StateMachineConfigurerAdapter<OrderState, OrderEvent> {
    
    @Override
    public void configure(StateMachineStateConfigurer<OrderState, OrderEvent> states) throws Exception {
        states
            .withStates()
                .initial(OrderState.CREATED)
                .state(OrderState.CREATED)
                .state(OrderState.PAID)
                .state(OrderState.SHIPPED)
                .state(OrderState.DELIVERED)
                .end(OrderState.CANCELLED);
    }
    
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderState, OrderEvent> transitions) throws Exception {
        transitions
            .withExternal().source(OrderState.CREATED).target(OrderState.PAID).event(OrderEvent.PAY)
            .and()
            .withExternal().source(OrderState.PAID).target(OrderState.SHIPPED).event(OrderEvent.SHIP)
            .and()
            .withExternal().source(OrderState.SHIPPED).target(OrderState.DELIVERED).event(OrderEvent.DELIVER)
            .and()
            .withExternal().source(OrderState.CREATED).target(OrderState.CANCELLED).event(OrderEvent.CANCEL)
            .and()
            .withExternal().source(OrderState.PAID).target(OrderState.CANCELLED).event(OrderEvent.CANCEL);
    }
}

// 订单实体 - Order Entity
@Entity
@Table(name = "orders")
public class Order {
    @Id
    private String orderId;
    private String customerName;
    private BigDecimal amount;
    
    @Enumerated(EnumType.STRING)
    private OrderState state;
    
    @Column(columnDefinition = "TEXT")
    private String stateMachineContext; // 存储状态机上下文(备忘录)
    
    // 构造函数、getters和setters
    public Order() {}
    
    public Order(String orderId, String customerName, BigDecimal amount) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.amount = amount;
        this.state = OrderState.CREATED;
    }
    
    // Getters and setters
    public String getOrderId() { return orderId; }
    public void setOrderId(String orderId) { this.orderId = orderId; }
    public String getCustomerName() { return customerName; }
    public void setCustomerName(String customerName) { this.customerName = customerName; }
    public BigDecimal getAmount() { return amount; }
    public void setAmount(BigDecimal amount) { this.amount = amount; }
    public OrderState getState() { return state; }
    public void setState(OrderState state) { this.state = state; }
    public String getStateMachineContext() { return stateMachineContext; }
    public void setStateMachineContext(String stateMachineContext) { this.stateMachineContext = stateMachineContext; }
}

// 订单服务 - Order Service
@Service
public class OrderService {
    private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
    private final StateMachine<OrderState, OrderEvent> stateMachine;
    private final OrderRepository orderRepository;
    
    @Autowired
    public OrderService(StateMachine<OrderState, OrderEvent> stateMachine, 
                       OrderRepository orderRepository) {
        this.stateMachine = stateMachine;
        this.orderRepository = orderRepository;
    }
    
    // 创建备忘录(保存状态机上下文)
    public String createStateMachineMemento() {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            stateMachine.getExtendedState().getVariables().forEach((key, value) -> {
                try {
                    oos.writeObject(new AbstractMap.SimpleEntry<>(key, value));
                } catch (IOException e) {
                    logger.error("序列化状态机变量失败", e);
                }
            });
            oos.close();
            return Base64.getEncoder().encodeToString(baos.toByteArray());
        } catch (IOException e) {
            logger.error("创建状态机备忘录失败", e);
            throw new RuntimeException("创建备忘录失败", e);
        }
    }
    
    // 从备忘录恢复(恢复状态机上下文)
    public void restoreStateMachineFromMemento(String mementoData) {
        try {
            byte[] data = Base64.getDecoder().decode(mementoData);
            ByteArrayInputStream bais = new ByteArrayInputStream(data);
            ObjectInputStream ois = new ObjectInputStream(bais);
            
            ExtendedState extendedState = stateMachine.getExtendedState();
            while (bais.available() > 0) {
                try {
                    @SuppressWarnings("unchecked")
                    Map.Entry<String, Object> entry = (Map.Entry<String, Object>) ois.readObject();
                    extendedState.getVariables().put(entry.getKey(), entry.getValue());
                } catch (EOFException e) {
                    break;
                }
            }
            ois.close();
            System.out.println("从备忘录恢复状态机上下文");
        } catch (IOException | ClassNotFoundException e) {
            logger.error("恢复状态机备忘录失败", e);
            throw new RuntimeException("恢复备忘录失败", e);
        }
    }
    
    // 处理订单事件
    @Transactional
    public void processOrderEvent(String orderId, OrderEvent event) {
        Order order = orderRepository.findById(orderId)
            .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
        
        // 恢复状态机状态
        if (order.getStateMachineContext() != null) {
            restoreStateMachineFromMemento(order.getStateMachineContext());
        }
        
        // 设置当前状态
        stateMachine.stop();
        stateMachine.getStateMachineAccessor().doWithAllRegions(access -> 
            access.resetStateMachine(new DefaultStateMachineContext<>(order.getState(), null, null, null)));
        
        // 发送事件
        Message<OrderEvent> message = MessageBuilder
            .withPayload(event)
            .setHeader("orderId", orderId)
            .build();
        
        stateMachine.start();
        stateMachine.sendEvent(message);
        
        // 获取新状态
        OrderState newState = stateMachine.getState().getId();
        order.setState(newState);
        
        // 保存状态机上下文(创建备忘录)
        String newContext = createStateMachineMemento();
        order.setStateMachineContext(newContext);
        
        orderRepository.save(order);
        
        logger.info("订单状态更新: {} -> {} for order: {}", order.getState(), newState, orderId);
    }
    
    // 创建订单并初始化状态机
    @Transactional
    public Order createOrder(String orderId, String customerName, BigDecimal amount) {
        Order order = new Order(orderId, customerName, amount);
        
        // 初始化状态机
        stateMachine.stop();
        stateMachine.start();
        
        // 创建初始备忘录
        String initialContext = createStateMachineMemento();
        order.setStateMachineContext(initialContext);
        
        order = orderRepository.save(order);
        logger.info("创建订单: {}", orderId);
        return order;
    }
    
    // 获取订单当前状态
    public OrderState getOrderState(String orderId) {
        return orderRepository.findById(orderId)
            .map(Order::getState)
            .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderId));
    }
}

// 客户端使用 - Client Usage
@SpringBootApplication
public class SpringStateMachineMementoDemo {
    
    public static void main(String[] args) {
        SpringApplication.run(SpringStateMachineMementoDemo.class, args);
        
        System.out.println("=== Spring状态机备忘录模式演示 ===");
        System.out.println("启动Spring Boot应用,测试状态机备忘录功能");
    }
    
    @Component
    public static class StateMachineMementoDemoRunner implements CommandLineRunner {
        
        @Autowired
        private OrderService orderService;
        
        @Override
        public void run(String... args) throws Exception {
            System.out.println("\n--- 开始Spring状态机备忘录模式演示 ---");
            
            // 创建订单
            String orderId = "ORDER-" + System.currentTimeMillis();
            Order order = orderService.createOrder(orderId, "张三", new BigDecimal("299.99"));
            System.out.println("订单初始状态: " + order.getState());
            
            // 处理订单事件
            System.out.println("\n--- 处理订单事件 ---");
            orderService.processOrderEvent(orderId, OrderEvent.PAY);
            System.out.println("支付后状态: " + orderService.getOrderState(orderId));
            
            orderService.processOrderEvent(orderId, OrderEvent.SHIP);
            System.out.println("发货后状态: " + orderService.getOrderState(orderId));
            
            orderService.processOrderEvent(orderId, OrderEvent.DELIVER);
            System.out.println("送达后状态: " + orderService.getOrderState(orderId));
            
            System.out.println("\nSpring状态机备忘录模式演示完成");
        }
    }
}

备忘录模式与其他模式比较 (Comparison with Other Patterns)

特性备忘录模式命令模式原型模式状态模式
目的状态保存恢复请求封装对象复制状态管理
关注点状态快照操作记录对象克隆状态转换
使用场景撤销/重做撤销/重做对象复制状态机
封装性保持封装可暴露操作暴露克隆状态封装
实现复杂度中等高低中等

最佳实践 (Best Practices)

1. 备忘录设计 (Memento Design)

  • 保持备忘录的不可变性
  • 只保存必要的状态信息
  • 考虑使用窄接口保护原发器的封装性

2. 原发器设计 (Originator Design)

  • 明确定义需要保存的状态
  • 提供清晰的创建和恢复方法
  • 考虑状态的验证和一致性检查

3. 管理者设计 (Caretaker Design)

  • 合理管理备忘录的生命周期
  • 考虑使用栈结构支持撤销/重做
  • 实现适当的内存管理策略

4. 性能优化 (Performance Optimization)

  • 使用增量备忘录减少内存占用
  • 考虑使用对象池重用备忘录对象
  • 实现适当的清理机制

5. 错误处理 (Error Handling)

  • 处理备忘录创建和恢复过程中的异常
  • 提供状态验证机制
  • 考虑实现回滚机制

优缺点 (Pros and Cons)

优点 (Advantages)

  • 保持封装性:不破坏对象的封装边界
  • 简化原发器:原发器不需要管理多个版本的状态
  • 支持撤销/重做:可以轻松实现撤销和重做功能
  • 状态历史:可以维护对象的状态历史
  • 检查点机制:支持创建状态检查点

缺点 (Disadvantages)

  • 内存消耗:保存大量状态可能消耗大量内存
  • 性能开销:创建和恢复备忘录需要时间
  • 实现复杂:需要仔细设计备忘录接口
  • 循环引用:可能导致循环引用问题
  • 状态一致性:需要确保状态的一致性

实际应用建议 (Practical Application Tips)

1. 状态选择

  • 只保存必要的状态信息
  • 避免保存冗余或计算得出的状态
  • 考虑状态的粒度和精度

2. 内存管理

  • 实现适当的清理机制
  • 考虑使用压缩技术减少内存占用
  • 合理设置备忘录数量限制

3. 并发处理

  • 在并发环境下确保线程安全
  • 考虑使用不可变对象
  • 处理好状态的同步问题

4. 测试策略

  • 测试备忘录的创建和恢复
  • 验证状态的一致性
  • 测试边界情况和异常处理

总结 (Summary)

备忘录模式是一种优雅的行为型设计模式,它通过在不破坏封装性的前提下捕获和保存对象的内部状态,为撤销/重做、状态回滚和历史记录等功能提供了强大的支持。这种模式在现代软件系统中有着广泛的应用,从文本编辑器的撤销功能到游戏存档系统,再到复杂的状态管理。

在实际应用中,备忘录模式特别适合以下场景:

  • 需要实现撤销/重做功能的应用程序
  • 需要保存对象历史状态的系统
  • 需要支持状态回滚的事务处理
  • 需要创建状态检查点的长时间运行程序
  • 需要实现状态快照的调试工具

通过合理使用备忘录模式,可以构建出功能丰富、用户友好的系统。然而,需要注意内存管理和性能优化,避免过度使用导致系统资源消耗过大。在设计时应该权衡好功能需求和系统资源之间的关系,确保系统的可扩展性和可维护性。

大数据领域数据服务的数据分析工具推荐 你有没有过这样的经历?——领导说“帮我分析一下上个月的销量”,你打开Excel却发现数据有100万行,电脑直接卡死;或者想实时知道“现在直播间的观众在买什么”,却不知道用什么工具处理每秒10万条的点击数据。本文的目的:帮你解决“选什么工具做什么事”的问题,覆盖大数据服务的全流程(采集→存储→处理→分析→可视化),推荐高频、实用、易上手的工具,并讲清楚它们的“适用场景”和“优缺点”。范围。 阅读详情

相关推荐

中兴FTTR光猫变简易OLT:低成本搭建全光监控与局域网实战指南

本文详细介绍了如何将中兴FTTR光猫改造为简易OLT设备,实现低成本全光监控与局域网扩展。通过LOID认证、桥接模式设置及终端数破解,用户可利用二手设备搭建高性能光纤网络,适用于远程监控和长距离组网场景,显著降低部署成本。

chair的专栏 2032

c++ 设计模式--备忘录模式(16)

案例:打游戏存档功能 备忘录模式 备忘录模式简介(MementoPattern) 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态。这样以后就可将该对象恢复到原先保存的状态。 备忘录模式结构 Originator(发起人):通过创建一个备忘录用以记录当前时刻它的内部状态,并可使用备忘录恢复内部状态。根据需要决定备忘录存储哪些状态 Memento(备忘录): 存储发起人对象的内部状态,并可防止发起人以外的其他对象访问备忘录 Caretaker(负责人): 负责保存好多个备忘录对象,

NiMiKiss的博客 192

避坑指南:MTK平台Widevine L1密钥安装全流程详解(含SP META工具使用与Log分析)

本文详细解析了MTK平台实现Widevine L1认证的全流程,涵盖密钥申请、格式转换、安全烧录等关键步骤,特别针对Trustonic TEE环境下的SP META工具使用与日志分析提供实用指南。帮助开发者规避常见错误,确保DRM密钥安全部署,满足高端内容保护需求。

weixin_27219587的博客 476

D23:C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】

一、引言 今天我们开始讲“行为型”设计模式的第十个模式,该模式是【备忘录模式】,英文名称是:Memento Pattern。按老规矩,先从名称上来看看这个模式,个人的最初理解就是对某个对象的状态进行保存,等到需要恢复的时候,可以从备忘录中进行恢复。生活中这样的例子也能经常看到,如备份电话通讯录,备份操作操作系统,备份数据库等。如果我们想恢复对象的状态,那么我们可能首先想到的是把对象保存下来,...

. 633

SVPWM原理与MCU/FPGA实现:从数学推导到工程实战

空间矢量调制(SVPWM)是实现高性能电机驱动控制的核心算法之一,其通过六个基本电压矢量与零矢量的伏秒平衡,在一个PWM周期内合成任意方向的旋转电压圆,相比传统SPWM可提升约15%的直流电压利用率。该技术不仅涉及扇区判断、作用时间计算、过调制限幅等数学原理,还在MCU与FPGA两种硬件平台上有不同的工程实现路径,包括中心对齐PWM配置、死区插入、定点数流水线设计等。在电动工具、无人机、机器人及车载执行器等电池供电场景中,SVPWM直接决定续航与扭矩表现。本文从数学原理出发,详细拆解MCU和FPGA实现细节

weixin_34265814的博客 301

YOLOv5改进之---EIoU,SIoU,AlphaIoU,FocalEIoU,Wise-IoU

本文主要针对yolov5的iou损失函数进行改进,主要涵盖EIoU,SIoU,AlphaIoU,FocalEIoU,Wise-IoU这几种损失

qq_41920323的博客 1465

38备忘录模式(Memento Pattern)

对象状态的回溯: 对象状态的变化无端,如何回溯/恢复对象在某个点的状态? 动机: 在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。 如何实现对象状态的良好保存与恢复?但同时又不会因此而破坏对象本...

sinolover的专栏 367

华为OD机试双机位C卷-FLASH坏块监测系统(Py/Java/C/C++/Js/Go)

华为OD机试(机考)双机位C卷 【FLASH坏块监测系统】,提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试 - FLASH坏块监测系统。

qq_45776114的博客 1928

Memento Design Pattern

Memento pattern is one of the behavioral design pattern. Memento design pattern is used when we want to save the state of an object so that we can restore later on. Memento pattern is used to implem...

cywhoyi的专栏 245

等保测评-达梦数据库

一般适用于等保测评

m0_54146694的博客 1297

物联网应用开发教程专栏介绍与说明——列表目录查阅(持续更新)

为方便查阅学习本专栏,特整理专栏介绍与说明及提供列表目录便于查阅。阿齐Archie《物联网应用开发教程》专栏。本专栏为物联网应用开发教程,将更新涵盖常见的WIFI、蓝牙、蜂窝网、以太网、Lora、NB-iot等物联网技术实战应用及详解其技术知识。专栏为技术文章,订阅一个文章即可本专栏内所有文章可看,实战开发,亲测无误,附视频演示效果,会持续更新本专栏。本专栏内有理论篇也有完整实战应用篇。

嵌入式阿齐Archie 2万+

C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】

C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】 原文:C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】一、引言 今天我们开始讲“行为型”设计模式的第十个模式,该模式是【备忘录模式】,英文名称是:Memento Pattern。按老规矩,先从名称上来看看这个模式,个人的最初理解就是对某个对...

weixin_30690833的博客 101

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

javascript设计模式--备忘录模式(Memento)

1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Memento</title> 6 </head> 7 <body> 8 9 ...

weixin_30950237的博客 127

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

备忘录模式(Memento Pattern)

对象状态的回溯:     对象状态的变化无端,如何回溯/恢复对象在某个点的状态?                         动机:     在软件构建过程中,某些对象的状态在转换过程中,可能由于某种需要,要求程序能够回溯到对象之前处于某个点时的状态。如果使用一些公有接口来让其他对象得到对象的状态,便会暴露对象的细节实现。     如何实现对象状态的良好保存与恢复?但同时又不会因...

weixin_34006965的博客 82

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

如何10分钟跑通react-design-patterns?新手快速入门教程,附5个可运行示例

react-design-patterns 是一个将经典面向对象设计模式(单例、中介者、桥接等)应用到 React 的开源研究项目,内置 5 个可直接运行的 React 示例。本教程面向新手,带你用不到 10 分钟完成 clone、安装、启动,并逐个理解每个设计模式示例在 React 中的落地方式,帮助你快速掌握 React 设计模式的核心思想。 ## 项目能给你带来什么? > 💡 一句话理

gitblog_00106的博客 1143

php设计模式目录

1:第 1 章 策略模式【STRATEGY PATTERN】 2:第 2 章 代理模式【PROXY PATTERN】 3:第 3 章 单例模式【SINGLETON PATTERN】 4:第 4 章 多例模式【MULTITION PATTERN】运行源码 5:第 5 章 工厂方法模式【FACTORY METHOD PATTERN】运行源码 6:第 6 章 抽象工厂模式【ABSTRACT F

ChenAiZiTeng的专栏 771

00.设计模式导读

经典的设计模式一般分为23中,分别如下 1、  策略模式    【STRATEGY PATTERN】 2、  代理模式    【PROXY PATTERN】 3   章  单例模式    【SINGLETON PATTERN】 第  4   章  多例模式    【MULTITION PATTERN】 第  5   章  工厂方法模式【FACTORY METHOD PATTERN】 第

技术小弟 432

设计模式

以前看过书,但要回忆起所有设计模式不可能,想继续搞高以及和别人交流,至少得把名称记住吧。到这把年纪了,要死记硬背是不可能的。即使是中学生,死计硬背下的东西如果不使用,过一段时间 也不可能记得住。 先列下《设计模式之禅》中的清单,然后尝试联想记忆。 第 1 章 策略模式【STRATEGY PATTERN】 ...................................... 第

trobin的专栏试 942

Android中的设计模式

中所提到的,总共有 23 种设计模式。这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。当然,我们还会讨论另一类设计模式:J2EE 设计模式。根据设计模式的参考书。

lhm1124的博客 1143

《JAVA面经实录》- SpringBoot 电商项目23种设计模式(三)

最终版·生产级 SpringBoot 电商项目: 已补全所有漏洞 + 23 种设计模式真实串联 + Spring 生态融合 + 可简历可面试可上线

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 556

《JAVA面经实录》- 23种设计模式面试题(二)

《JAVA设计模式面试精要》摘要:本文系统解析23种设计模式,分为创建型(单例、工厂等)、结构型(适配器、代理等)和行为型(观察者、策略等)三大类。重点阐述六大设计原则(SOLID+迪米特法则),每个模式均包含定义、原则应用、优缺点分析及典型业务场景(如电商支付、审批系统等),并附Java代码实现。特别强调模式选择需结合实际需求,避免过度设计,同时提供清晰的模式对比表格,帮助开发者快速掌握各模式核心特征与应用场景。

专注 Java 后端开发,分享基础语法、JVM、并发、Spring 全家桶、微服务、分布式、性能优化等实战干货。坚持输出高质量技术笔记,用简单语言讲清复杂原理,助力每一位 Java 开发者稳步进阶。 894

设计模式之享元模式(Flyweight)摘录

设计模式之享元模式(Flyweight)摘录

网络资源是无限的 2687
上一篇: 设计模式-15中介者模式Mediator Pattern
下一篇: 设计模式-17观察者模式Observer Pattern
d3y1
博客等级 码龄12年 1438粉丝 2777原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值