Design mode memo + command mode implements Word undo and recovery operations

Preface

I recently learned the behavioral pattern of design patterns. I learned about the memo pattern and mentioned that this pattern can record the state attribute value of an object for reuse next time. Then I thought of the undo operation we use on the Windows system, so I thought about it. Let’s use this pattern to simulate and reproduce

Ideas

The following is a description based on the combination of memo and command mode:

  1. First, we have a document class Documentthat contains a text property. The Document class provides methods for setting and getting text.

  2. We introduce the memo class Mementoto save the state of the document object.

  3. The document class also implements methods for creating memos and restoring memos. When creating a memo, the document object passes the current text state to the memo object for saving. When restoring a memo, the document object obtains the previously saved text state from the memo object and restores it.

  4. In order to implement reversible operations and undo functions, we introduce a command interface Command, which defines execution methods execute()and undo methods undo().

  5. The specific command class InsertTextCommandis a specific implementation of the insert text operation. When executing a command, the command object calls the insert text method of the document object and saves the text state before execution to the memo object. When the command is undone, the command object uses the memo object to restore the document's textual state.

  6. The history class Historyplays the role of the caller and is used to record the executed commands. It uses a list internally to save command objects. Each time a command is executed, the command object is added to the list and saved; each time a command is canceled, the last command object in the list is taken out and its undo operation is performed.

  7. In the main program, we instantiate the document object, memo object and history object.

  8. Execute the insert text command 1, create the insert text command object and add it to the list of history objects. This command object will perform the text insertion operation and save the text state before execution to the memo object.

  9. Execute the Insert Text command 2, also create the Insert Text command object and add it to the list of history objects. The command object will also perform the text insertion operation and save the text state before execution to the memo object.

  10. Execute the undo command, take out the last command object (ie insert text command 2) from the list of history objects, and perform its undo operation. The command object will retrieve the previously saved text state from the memo object and restore the document's content.

  11. Output the content of the document, that is, output "Hello".

  12. Execute the undo command again, remove the insert text command 1 from the list of history objects, and perform its undo operation. The contents of the document become an empty string.

  13. Output the contents of the document, that is, output an empty string.

  14. Try to execute the undo command again. Since there are no undoable commands in the history, no operation will be performed.

  15. Finally, the content of the document is output, and the empty string is still output.

Code

To implement undo and restore operations similar to those in Word documents, you can use memo mode and command mode.

  1. Memento: The memento class is responsible for storing the status of the document. It can save the content, style, cursor position and other information of the document.
class Memento {
    
    
    private String content;
    private String style;
    private int cursorPosition;

    // 构造函数和访问方法
}
  1. Command interface (Command): The command interface defines methods to perform and undo operations.
interface Command {
    
    
    void execute();
    void undo();
}
  1. Specific command class (specific operation): implements the command interface and performs and cancels specific operations on the document. For example, insert text, modify styles, move the cursor, etc.
class InsertTextCommand implements Command {
    
    
    private Document document;
    private Memento prevState;
    private String newText;

    public InsertTextCommand(Document document, String newText) {
    
    
        this.document = document;
        this.newText = newText;
    }

    public void execute() {
    
    
        prevState = document.createMemento();
        document.setText(newText);
    }

    public void undo() {
    
    
        document.restore(prevState);
    }
}
  1. Document class (Originator): The document class maintains the state of the document and provides methods for creating memos, restoring state, and performing operations.
class Document {
    
    
    private String text;

    public void setText(String text) {
    
    
        this.text = text;
    }

    public String getText() {
    
    
        return text;
    }

    public Memento createMemento() {
    
    
        return new Memento(text);
    }

    public void restore(Memento memento) {
    
    
        text = memento.getState();
    }
}
  1. History class (Caretaker): The history class is responsible for storing memo objects and managing commands to perform and undo operations.
class History {
    
    
    private Stack<Command> commandStack;

    public History() {
    
    
        commandStack = new Stack<>();
    }

    public void executeCommand(Command command) {
    
    
        command.execute();
        commandStack.push(command);
    }

    public void undo() {
    
    
        if (!commandStack.isEmpty()) {
    
    
            Command command = commandStack.pop();
            command.undo();
        }
    }
}

Sample code using the above design is as follows:

    public static void main(String[] args) {
    
    
        // 创建文档对象和历史记录对象
        Document document = new Document();
        History history = new History();

        // 执行命令:插入文本
        Command insertCommand1 = new InsertTextCommand(document, "Hello");
        history.executeCommand(insertCommand1);

        // 执行命令:插入文本
        Command insertCommand2 = new InsertTextCommand(document, " World!");
        history.executeCommand(insertCommand2);
        

        // 输出文档内容
        System.out.println(document.getText());  // 输出:World!

        // 执行命令:撤销上一个命令
        history.undo();

        // 输出文档内容
        System.out.println(document.getText());  // 输出:hello

        // 执行命令:撤销上一个命令(没有可撤销的命令)
        history.undo();  // 不执行任何操作

        // 输出文档内容
        System.out.println(document.getText());  // 输出:""
    }

Insert image description here

By using memo mode and command mode, we can record changes in document status and perform undo and restore operations when needed. Each time an operation is performed, a corresponding command object is created and added to the history to support undo and redo operations.

uml class diagram

Insert image description here

Summarize

The implementation of this function uses two design modes: memo mode and command mode.

The memo mode is used to save the state of document objects and provides the function of restoring the state. It encapsulates the state of the document object in a memo object so that it can be saved and restored when needed. In this way, the state management and rollback functions of the document object can be realized without destroying the encapsulation of the document object.

Command mode is used to perform and undo operations. By encapsulating each operation in a command object and providing unified execution and undo methods, unified management and control of operations can be achieved. In this way, different operations can be easily extended and combined, while also decoupling the caller and receiver.

Benefits of using design patterns include:

  1. Improve code maintainability and scalability: Design patterns make the code structure clearer and easier to understand and maintain. Clear roles and relationships are defined in the schema, making the code well-organized and scalable.

  2. Increased reusability: Design patterns allow code to be reused in different scenarios by providing common solutions. This avoids repeatedly writing similar code and improves development efficiency.

  3. Reduce coupling: Design patterns minimize dependencies between components in the system by clarifying roles and relationships. In this way, when requirements change or a certain component needs to be modified, it will have minimal impact on other components, making it easy to maintain and expand.

  4. Improve code testability: Design patterns separate logic so that each module can be tested independently, making it easier to write unit tests and integration tests.

Guess you like

Origin blog.csdn.net/pengjun_ge/article/details/132527692