Design Patterns: Memento

Memento design pattern. Image by Author via Canva.com

The memento design pattern provides us the very useful functionality of reverting to a previous state of an object when needed. It comprises of three different roles that will have to be created in order for it to work. These three roles are:

  1. Originator- The originator is the object that will be saving its state for us to revert to later.
  2. Caretaker- This is the object that will save as well as restore the state of the originator when each of these actions are required.
  3. Memento- The memento is the object that will be used by the caretaker to store the state of the originator. The originator will write their state to the memento when it is being saved, and read from it when the state is being reverted.

Implementing the Memento Design Pattern

Assume we have a music application and we start listening to songs one after the other. At some point we would hear an amazing song that you feel like you need to listen to it again because it was just that good! Instead of searching for the song again you click the previous track button. To do this we will implement the program using the memento design pattern so that we can go back and play that song one more time.

First let us create a class called ‘NowPlaying’ that will assume the role of the originator in this example.

public class NowPlaying {
private String currentSong;
public void play(String song) {
this.currentSong = song;
}
private String getCurrentSong() {
return currentSong;
}
@Override
public String toString() {
return "Now playing: " + currentSong;
}
}

Now that we have that ready we need to create the class that will act as the memento. We can call this ‘NowPlayingMemento’ and I am implementing it as an inner class so that it can be accessed through the ‘NowPlaying’ class. The ‘NowPlaying’ class will now look like this:

public class NowPlaying {
   private String currentSong;
   public void play(String song) {
this.currentSong = song;
}
   private String getCurrentSong() {
return currentSong;
}
   public NowPlayingMemento save() {
return new NowPlayingMemento(getCurrentSong());
}
   public void previous(NowPlayingMemento nowPlayingMemento) {
this.currentSong = nowPlayingMemento.getSong();
}
   @Override
public String toString() {
return "Now playing: " + currentSong;
}
   static class NowPlayingMemento {
      private String song;
      public NowPlayingMemento(String song) {
this.song = song;
}
      private String getSong() {
return song;
}
   }
}

I have emphasized the lines of code that I have added to make it easier to understand.

Now it is time to create the class that will be used as the caretaker for this example. We will create a class called ‘PlayedHistory’ and this will have a stack that stores instances of ‘NowPlayingMemento’ to be used to move to previously played songs one by one.

import java.util.Stack;
public class PlayedHistory {
   Stack<NowPlaying.NowPlayingMemento> history = new Stack<>();
   public void save(NowPlaying nowPlaying) {
history.push(nowPlaying.save());
}
   public void previous(NowPlaying nowPlaying) {
if(!history.isEmpty()) {
nowPlaying.previous(history.pop());
} else {
System.out.println("End of played history.");
}
}
}

We have used an if-condition to check if the stack is empty before ‘popping’ out the last saved song. Now let’s create a class to see this music player in action.

public class Application {
   public static void main(String[] args) {
      PlayedHistory history = new PlayedHistory();
      NowPlaying nowPlaying = new NowPlaying();
      nowPlaying.play("Sweet Child o' Mine");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Back In Black");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Disenchanted");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Say Amen");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("House of Wolves");
history.save(nowPlaying);
System.out.println(nowPlaying);
      // Going back to previous songs
history.previous(nowPlaying);
System.out.println(nowPlaying);
      history.previous(nowPlaying);
System.out.println(nowPlaying);
      history.previous(nowPlaying);
System.out.println(nowPlaying);
   }
}

To test the application we created one instance each of the ‘PlayedHistory’ class and ‘NowPlaying’ class. After every call of the play() method we called history.save() to save the memento of the current song to the stack. Once we finished playing all the songs we went back to the previously played songs one by one and got the following output (please ignore my music taste…).

Now playing: Sweet Child o' Mine
Now playing: Back In Black
Now playing: Disenchanted
Now playing: Say Amen
Now playing: House of Wolves
Now playing: House of Wolves
Now playing: Say Amen
Now playing: Disenchanted

You will see the last song (House of Wolves) plays twice. This is because we save the song to the stack right after we play it, so we will see the last one replayed before going back (this would anyway be the case with music players most of the time).

Note: This is just a simple take on a music player for the purpose of providing an example on how this design pattern can be used.

I hope this article provided you some useful information on the memento design pattern. Thanks for reading!

References

Videos

Undo changes with Memento pattern | Design patterns you must know


Design Patterns: Memento was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Aaron De Zoysa

Memento design pattern. Image by Author via Canva.com

The memento design pattern provides us the very useful functionality of reverting to a previous state of an object when needed. It comprises of three different roles that will have to be created in order for it to work. These three roles are:

  1. Originator- The originator is the object that will be saving its state for us to revert to later.
  2. Caretaker- This is the object that will save as well as restore the state of the originator when each of these actions are required.
  3. Memento- The memento is the object that will be used by the caretaker to store the state of the originator. The originator will write their state to the memento when it is being saved, and read from it when the state is being reverted.

Implementing the Memento Design Pattern

Assume we have a music application and we start listening to songs one after the other. At some point we would hear an amazing song that you feel like you need to listen to it again because it was just that good! Instead of searching for the song again you click the previous track button. To do this we will implement the program using the memento design pattern so that we can go back and play that song one more time.

First let us create a class called ‘NowPlaying’ that will assume the role of the originator in this example.

public class NowPlaying {
private String currentSong;
public void play(String song) {
this.currentSong = song;
}
private String getCurrentSong() {
return currentSong;
}
@Override
public String toString() {
return "Now playing: " + currentSong;
}
}

Now that we have that ready we need to create the class that will act as the memento. We can call this ‘NowPlayingMemento’ and I am implementing it as an inner class so that it can be accessed through the ‘NowPlaying’ class. The ‘NowPlaying’ class will now look like this:

public class NowPlaying {
   private String currentSong;
   public void play(String song) {
this.currentSong = song;
}
   private String getCurrentSong() {
return currentSong;
}
   public NowPlayingMemento save() {
return new NowPlayingMemento(getCurrentSong());
}
   public void previous(NowPlayingMemento nowPlayingMemento) {
this.currentSong = nowPlayingMemento.getSong();
}
   @Override
public String toString() {
return "Now playing: " + currentSong;
}
   static class NowPlayingMemento {
      private String song;
      public NowPlayingMemento(String song) {
this.song = song;
}
      private String getSong() {
return song;
}
   }
}

I have emphasized the lines of code that I have added to make it easier to understand.

Now it is time to create the class that will be used as the caretaker for this example. We will create a class called ‘PlayedHistory’ and this will have a stack that stores instances of ‘NowPlayingMemento’ to be used to move to previously played songs one by one.

import java.util.Stack;
public class PlayedHistory {
   Stack<NowPlaying.NowPlayingMemento> history = new Stack<>();
   public void save(NowPlaying nowPlaying) {
history.push(nowPlaying.save());
}
   public void previous(NowPlaying nowPlaying) {
if(!history.isEmpty()) {
nowPlaying.previous(history.pop());
} else {
System.out.println("End of played history.");
}
}
}

We have used an if-condition to check if the stack is empty before ‘popping’ out the last saved song. Now let’s create a class to see this music player in action.

public class Application {
   public static void main(String[] args) {
      PlayedHistory history = new PlayedHistory();
      NowPlaying nowPlaying = new NowPlaying();
      nowPlaying.play("Sweet Child o' Mine");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Back In Black");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Disenchanted");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("Say Amen");
history.save(nowPlaying);
System.out.println(nowPlaying);
      nowPlaying.play("House of Wolves");
history.save(nowPlaying);
System.out.println(nowPlaying);
      // Going back to previous songs
history.previous(nowPlaying);
System.out.println(nowPlaying);
      history.previous(nowPlaying);
System.out.println(nowPlaying);
      history.previous(nowPlaying);
System.out.println(nowPlaying);
   }
}

To test the application we created one instance each of the ‘PlayedHistory’ class and ‘NowPlaying’ class. After every call of the play() method we called history.save() to save the memento of the current song to the stack. Once we finished playing all the songs we went back to the previously played songs one by one and got the following output (please ignore my music taste…).

Now playing: Sweet Child o' Mine
Now playing: Back In Black
Now playing: Disenchanted
Now playing: Say Amen
Now playing: House of Wolves
Now playing: House of Wolves
Now playing: Say Amen
Now playing: Disenchanted

You will see the last song (House of Wolves) plays twice. This is because we save the song to the stack right after we play it, so we will see the last one replayed before going back (this would anyway be the case with music players most of the time).

Note: This is just a simple take on a music player for the purpose of providing an example on how this design pattern can be used.

I hope this article provided you some useful information on the memento design pattern. Thanks for reading!

References

Videos

Undo changes with Memento pattern | Design patterns you must know


Design Patterns: Memento was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Aaron De Zoysa


Print Share Comment Cite Upload Translate Updates
APA

Aaron De Zoysa | Sciencx (2022-03-27T15:28:31+00:00) Design Patterns: Memento. Retrieved from https://www.scien.cx/2022/03/27/design-patterns-memento/

MLA
" » Design Patterns: Memento." Aaron De Zoysa | Sciencx - Sunday March 27, 2022, https://www.scien.cx/2022/03/27/design-patterns-memento/
HARVARD
Aaron De Zoysa | Sciencx Sunday March 27, 2022 » Design Patterns: Memento., viewed ,<https://www.scien.cx/2022/03/27/design-patterns-memento/>
VANCOUVER
Aaron De Zoysa | Sciencx - » Design Patterns: Memento. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/03/27/design-patterns-memento/
CHICAGO
" » Design Patterns: Memento." Aaron De Zoysa | Sciencx - Accessed . https://www.scien.cx/2022/03/27/design-patterns-memento/
IEEE
" » Design Patterns: Memento." Aaron De Zoysa | Sciencx [Online]. Available: https://www.scien.cx/2022/03/27/design-patterns-memento/. [Accessed: ]
rf:citation
» Design Patterns: Memento | Aaron De Zoysa | Sciencx | https://www.scien.cx/2022/03/27/design-patterns-memento/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.