Skip to content

Instantly share code, notes, and snippets.

@joe-sharp
Last active November 26, 2020 18:19
Show Gist options
  • Save joe-sharp/ee52e8f795c947f000eee6505b39295c to your computer and use it in GitHub Desktop.
Save joe-sharp/ee52e8f795c947f000eee6505b39295c to your computer and use it in GitHub Desktop.
Memento Design Pattern in Ruby
class Memento
attr_accessor :state
def initialize(state)
@state = state
end
end
class Caretaker
attr_reader :memento
def save(memento)
@memento = memento
end
end
# Usage:
class VideoGame
attr_accessor :state
def initialize(state={})
@state = state
end
def save
Memento.new(@state)
end
def restore(memento)
@state = memento.state
end
end
RSpec.describe 'Memento' do
before(:all) do
@memory_card = Array.new(8, Caretaker.new)
@session = VideoGame.new(name: 'Joe', level: 0)
end
it 'performs initial game save' do
@memory_card[0].save(@session.save)
expect(@memory_card[0].memento.state).to eq(@session.state)
end
it 'overwrites game saves' do
original_state = @memory_card[0].memento.state
@session.state[:level] = 1
@memory_card[0].save(@session.save)
expect(@memory_card[0].memento).not_to eq(original_state)
end
it 'can restore game saves' do
original_state = @memory_card[0].memento.state
@session.state[:level] = nil
@session.restore(@memory_card[0].memento)
expect(@session.state).to eq(original_state)
end
it 'cannot corrupt game saves' do
expect { @memory_card[0].memento = nil }.to raise_error(NoMethodError)
end
end
@joe-sharp
Copy link
Author

joe-sharp commented Aug 8, 2020

The original Ruby implementation I saw was created by D.L. Jerome
One notable improvement I have made in the implementation is that the Caretaker is only able to overwrite/return a memento but is not permitted to access it directly. To me this is an important characteristic of the Memento design pattern as it ensures encapsulation is not broken throughout the life of the memento.

Additionally I have included the usage as if it were being added to a video game which personally makes patterns easier for me to relate to. For simpler usage, background information, or to compare implementations please visit D.L. Jerome's write up on the pattern here: https://medium.com/@dljerome/design-patterns-in-ruby-memento-1287f926fd0a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment