Showing posts with label Code Walkthrough. Show all posts
Showing posts with label Code Walkthrough. Show all posts

Sunday, 24 November 2013

Memento Design pattern - Implementation

🚀 Master Java Design Patterns & Software Architecture!

Subscribe to Ram N Java for clean software architecture patterns, design pattern deep dives, and production-ready implementation guides!

🔔 Subscribe to Ram N Java

Implementing the Memento Design Pattern in Java

In modern application design, preserving and restoring previous states—such as implementing undo/redo functionality, transactional rollbacks, or snapshot checkpoints—is a common necessity. However, exposing internal fields to external objects breaks encapsulation. The Memento Design Pattern solves this challenge cleanly by capturing and externalizing an object’s internal state so that it can be restored later without violating data encapsulation boundaries.

Key Components & Architecture

  • Originator: The core object containing the active state. It creates a snapshot of its internal state into a Memento object and restores its state when supplied with a previously saved Memento.
  • Memento: An immutable value object that securely encapsulates the internal state of the Originator. It provides restricted visibility to protect state data from unauthorized modification.
  • Caretaker: Responsible for tracking and storing Memento instances (e.g., maintaining an undo stack or history list) without inspecting or modifying the contents of the mementos.

Implementation Best Practices & Guidelines

  1. Protect Encapsulation: Ensure the Memento provides a wide interface to the Originator (allowing full state extraction/restoration) and a narrow interface to the Caretaker (preventing access to internal state variables).
  2. Enforce Immutability: Design Memento objects as immutable state containers so saved checkpoints cannot be altered after creation.
  3. Manage State Footprint: Storing full snapshots can consume significant memory. For large objects, consider delta-based state capture or limiting the history stack capacity.
  4. Leverage Inner Classes: Defining the Memento as a private inner class within the Originator allows seamless private field access while keeping the state strictly inaccessible to external consumers.

Why Proper Implementation Matters

  • Zero Encapsulation Violation: Internal state details remain strictly private to the Originator, keeping class boundaries pristine.
  • Simplified Originator Architecture: The Originator does not need to manage history management, stack structures, or archival logic—the Caretaker handles these lifecycle operations.
  • Predictable Undo/Redo Mechanisms: Simplifies complex multi-step state rollbacks across enterprise desktop, mobile, and web applications.

Recommended Next Videos

Continue your deep dive into the Memento pattern and behavioral design patterns with these related tutorials from our channel:


Click here to watch in Youtube : https://www.youtube.com/watch?v=ZjouanHQmdk

Click the below Image to Enlarge
Memento Design pattern - Implementation
Memento Design pattern - Class Diagram








































LedTV.java

public class LedTV
{
private String  size;
private String  price;
private boolean usbSupport;

public LedTV( String size, String price, boolean usbSupport )
{
super();
this.size = size;
this.price = price;
this.usbSupport = usbSupport;
}

public String getSize()
{
return size;
}

public void setSize( String size )
{
this.size = size;
}

public String getPrice()
{
return price;
}

public void setPrice( String price )
{
this.price = price;
}

public boolean isUsbSupport()
{
return usbSupport;
}

public void setUsbSupport( boolean usbSupport )
{
this.usbSupport = usbSupport;
}

@Override
public String toString()
{
return "LedTV [size=" + size + ", price=" + price + ", usbSupport=" + usbSupport + "]";
}

}


Memento.java

public class Memento
{
private LedTV ledTV;

public Memento( LedTV ledTV )
{
super();
this.ledTV = ledTV;
}

public LedTV getLedTV()
{
return ledTV;
}

public void setLedTV( LedTV ledTV )
{
this.ledTV = ledTV;
}

@Override
        public String toString()
        {
       return "Memento [ledTV=" + ledTV + "]";
        }

}

Caretaker.java

import java.util.ArrayList;
import java.util.List;
/*
 * Store Room
 */
public class Caretaker
{
private List<Memento> ledTvList = new ArrayList<Memento>();

public void addMemento( Memento m )
{
ledTvList.add(m);
System.out.println("LED TV's snapshots Maintained by CareTaker :" + ledTvList);
}

public Memento getMemento( int index )
{
return ledTvList.get(index);
}
}


Originator.java

/*
 * Hall
 */
public class Originator
{
LedTV ledTV;

public LedTV getLedTV()
{
return ledTV;
}

public void setLedTV( LedTV ledTV )
{
this.ledTV = ledTV;
}

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

public void setMemento( Memento memento )
{
ledTV = memento.getLedTV();
}

@Override
        public String toString()
        {
       return "Originator [ledTV=" + ledTV + "]";
        }

}

MementoClient.java

public class MementoClient
{

public static void main( String[] args )
{
Originator originator = new Originator();
originator.setLedTV(new LedTV("42 inch", "60000Rs", false));

Caretaker caretaker = new Caretaker();
caretaker.addMemento(originator.createMemento());

originator.setLedTV(new LedTV("46 inch", "80000Rs", true));
caretaker.addMemento(originator.createMemento());

originator.setLedTV(new LedTV("50 inch", "100000Rs", true));
System.out.println("\nOrignator current state : " + originator);

System.out.println("\nOriginator restoring to 42 inch LED TV...");

originator.setMemento(caretaker.getMemento(0));

System.out.println("\nOrignator current state : " + originator);

}

}

Output

LED TV's snapshots Maintained by CareTaker :[Memento [ledTV=LedTV [size=42 inch, price=60000Rs, usbSupport=false]]]
LED TV's snapshots Maintained by CareTaker :[Memento [ledTV=LedTV [size=42 inch, price=60000Rs, usbSupport=false]], Memento [ledTV=LedTV [size=46 inch, price=80000Rs, usbSupport=true]]]

Orignator current state : Originator [ledTV=LedTV [size=50 inch, price=100000Rs, usbSupport=true]]

Originator restoring to 42 inch LED TV...

Orignator current state : Originator [ledTV=LedTV [size=42 inch, price=60000Rs, usbSupport=false]]

See also:

  • Momento Design pattern - Introduction
  • Momento Design pattern - Real time Example
  • Memento Design pattern - Class Diagram
  • Memento Design pattern - Sequence Diagram
  • Momento Design pattern - KeyPoints
  • All Design Patterns Links
  • Tutorials