Skip to content

nasccped/DP-undo-redo-example

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

24 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DP-undo-redo-example

built in project kind: java

This repository is an attempt to implement the undo-redo feature introduced at Design Patters: Elements of Reusable Object-Oriented Software1 book (page 62/358).

Basically, the book give us a problem to be solved by the following though:

image 1: undo redo example

image 1: undo redo example

The user is facing a program's state. It can go back to previous states and also go to next states (since the undo store the states which can be reaplied).

My solution approach is a stack based object: (suitable for LIFO2 problems).

image 2: solution approach

image 2: solution approach

Now, we can:

  • insert incoming objects (states) in our undo stack,
  • get the current state with peek (undo top state = current state),
  • send top state from undo to redo stack whenever we call the undo action,
  • send top element from redo to undo stack whenever we call the redo action,
  • clear redo stack whenever a new states comes in our "UndoRedo" machine.

Cloning, compiling and running

To clone the project you can:

# clone using git
git clone https://github.com/nasccped/DP-undo-redo-example
# remove git folder (works for bash based terminals, only)
rm -rf DP-undo-redo-example/.git/
# goto dir
cd DP-undo-redo-example

Compiling

Since this project was built under the kojamp3 project manager, you can use it to handle the project, or:

  • compile using a bash terminal (Linux):
javac $(find src -type f -name **.java) -d out
  • compile using a powershell terminal (Windows):
javac (Get-ChildItem -Recurse -Path src -Filter *.java | ForEach-Object { $_.FullName }) -d out

Finally, you can execute the program by running:

java --class-path out UndoRedoExample

Where's the Command pattern?

On the Design Patterns1 book, this kind of problem is used to exemplify the Lexi's4 program building.

The author enforces that our program must be able to execute (and "unexecute") some actions. Command is a great design pattern to this job!

However, I just want to provide this thinking technology of "goNext/goPrevious" in a machine state timeline (shown in image 1).

How our app works?

Our app can be separated into three pieces:

  1. user input catching+parsing
  2. the machine itself
  3. utilities used throughout the code

User input

Before defining the valid user input values, we should think about how our machine works.

Machine's policy

The machine doesn't work with real states and commands, but it should store values as states and run actions. They both come from the user input's default type (String).

With this in mind, we should be able to turn Strings into state value's or action's types (from the self String value).

Let's consider:

  • unsigned integer (0, 312981, ...): as state value's type
  • action entries (do_it, d, ...): as action kind type

Now, we can parse user input (String) to value (Integer) or action (Action) type:

user input type inner value
String("dothis") Action do this action
String("dothat") Action do that action
String("123") Value 123
... ... ...

All this stuff is done by the userinput package. String input is parsed by the UserInputStrategy object, and converted to an AbstractUserInput child object (like an enum variant).

Undo/Redo machine

Controller

The undo-redo machine stores it's inner attributes (undo and redo stacks, coloring styles, inner report). You can call any UndoRedoMachine method as long as this doesn't change the inner attributes, otherwise, you'll need to call methods from the MachineController, which provides methods to handle user input (change machine's inner state) and to update machine's report.

Commands

The machine provides four different kind of commands:

command alias description
undo u pop an element from undo stack and send it to redo stack
redo r pop an element from redo stack and send it to undo stack
<unsigned int> (insert) - insert an element into our machine (to undo stack)
quit q ends the machine process
Command rules

The undo command will works only if the undo stack isn't empty. The redo command/stack follows the same rule.

Whenever a new item is pushed to our machine, the redo stack will be clear.

Utils

This project provides four utils only:

  1. Colors: a shortcut to use ANSI5 color escapes without code repetition
  2. Printer: a shortcut to avoid Sytem.out.println in the entire code
  3. ScannerUtil: same as bullet above, but for input getting
  4. Strategy: an interface used to return specific outputs based on a defined input

Footnotes

  1. Design Patters: Elements of Reusable Object-Oriented Software is a software engineering book that describes software design patterns. You can find it at amazon website. ↩ ↩2 ↩3

  2. LIFO is a principle which dictates that the most recently added element to a collection is the first one to be removed or processed. This is analogous to a stack of plates. ↩

  3. Kojamp is a Java and Kotlin project manager I built. You can find more info on it's official repository ↩

  4. Lexi is a hypothetical word processor that the authors use throughout the Design Patterns1 book as a running example to demonstrate different design patterns. ↩

  5. ANSI escape sequences are a standard for in-band signaling to control cursor location, color, font styling, and other options on video text terminals and terminal emulators. ↩

About

📖 undo redo example (from Design Patterns book) implementation in java

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages