Skip to content

CSCI 370 Lec 16: Iterator and Command Design Patterns

Thursday, April 10


The Memento Pattern is a design pattern that captures and stores the state of an object so it can be restored later without exposing its internal structure. This is commonly used in undo/redo systems.

  • Originator: The object whose state we want to save. For example, a Document object that holds some content.
  • Memento: A snapshot of the originator’s internal state. This object is immutable and doesn’t expose any functionality.
  • Caretaker: Manages when to save or restore the originator’s state using mementos. It does not know or depend on the details of the saved state.

Example: In a text editor, you might save the state of a document before a change so that it can be restored if the user hits “undo.”


The Iterator Pattern provides a way to access the elements of a collection one at a time without exposing how the collection is implemented.

The Iterator Pattern solves the problem of tight coupling between the internal data structure of a collection and the client code that uses it.

Example:

Teacher[] teachers = school.getTeachers();
for (int i = 0; i < 100; i++) {
System.out.println(teachers[i].name);
}

If a School class internally uses an array to store Teacher objects, and external code loops over that array directly, the client becomes tightly coupled to the array implementation. Any future changes to the data structure (e.g., switching from an array to a list) would break all the dependent code.

Instead of directly exposing the internal array, School2 returns an iterator that hides the implementation details:

public interface Iterator {
boolean hasNext();
Object next();
}

This interface defines two methods:

  • hasNext(): returns true if there are more elements.
  • next(): returns the next element in the collection.

The School2 class uses an inner class TeacherIterator to implement this pattern.

private class TeacherIterator implements Iterator {
int pos = 0;
public boolean hasNext() {
return pos <= 99;
}
public Object next() {
return teachers[pos++];
}
}
School2 school2 = new School2();
Iterator iterator = school2.getTeachers();
while (iterator.hasNext()) {
System.out.println(((Teacher)iterator.next()).name);
}

This setup ensures the main method doesn’t care how the teachers are stored inside the school object. The internal array is abstracted away.

  • Reduces coupling between collection and client code
  • Makes code more maintainable and flexible
  • Supports different storage implementations without affecting iteration logic

In applications like word processors, users perform actions (e.g., bold text, undo, redo). These user actions need to be encapsulated, stored, and optionally undone or redone.

The Command Pattern turns a request into a standalone object that contains all information about the request. It’s especially useful for actions that might be undone, redone, queued, or logged.

Interface:

public interface Command {
void execute();
void unexecute();
}
public class BoldContent implements Command {
HtmlDocment htmlDocment;
public BoldContent(HtmlDocment htmlDocment) {
this.htmlDocment = htmlDocment;
}
public void execute() {
htmlDocment.content = "<b>" + htmlDocment.content + "</b>";
}
public void unexecute() {
htmlDocment.content = htmlDocment.content.replace("<b>", "");
htmlDocment.content = htmlDocment.content.replace("</b>", "");
}
}

The HtmlDocment class simply holds a String content field:

public class HtmlDocment {
public String content;
}
List<Command> commands = new ArrayList<>();
HtmlDocment doc = new HtmlDocment();
doc.content = "Hello World!";
Command bold = new BoldContent(doc);
commands.add(bold);
for (Command c : commands)
c.execute();
for (Command c : commands)
c.unexecute();

The action of making content bold (and undoing it) is now encapsulated in an object. This makes it easier to implement undo/redo functionality and action history.

  • Text editors (bold, italic, undo, redo)
  • Macros
  • Transaction systems
  • UI event handling
  • Encapsulates behavior as objects
  • Easy to extend with new commands
  • Simplifies undo/redo logic
  • Decouples invoker from action logic

PatternPurposeStructure/ComponentsBenefits
MementoSave/restore internal state of an objectOriginator, Memento, CaretakerSupports undo/redo without violating encapsulation
IteratorTraverse a collection without exposing its structureIterator interface with hasNext() and next()Decouples client from collection implementation
CommandEncapsulate requests as objects (e.g., user actions)Command interface, concrete command classes, receiversEnables undo, redo, and action logging

These three design patterns each solve common problems in software design, especially in systems where you need flexibility, encapsulation, and maintainability.