Last active
November 26, 2020 18:19
-
-
Save joe-sharp/ee52e8f795c947f000eee6505b39295c to your computer and use it in GitHub Desktop.
Memento Design Pattern in Ruby
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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