From 6aaffecdba7ac35be3a0d3d0717dc13ca0a7ec65 Mon Sep 17 00:00:00 2001 From: Cotel Date: Mon, 24 Apr 2017 16:11:51 +0200 Subject: [PATCH 1/2] Added Memento pattern --- README.md | 34 +++++++++++++++-- src/main/kotlin/oop/Memento/CareTaker.kt | 5 +++ src/main/kotlin/oop/Memento/Memento.kt | 3 ++ src/main/kotlin/oop/Memento/Originator.kt | 8 ++++ src/test/kotlin/oop/Memento/MementoTest.kt | 43 ++++++++++++++++++++++ 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/oop/Memento/CareTaker.kt create mode 100644 src/main/kotlin/oop/Memento/Memento.kt create mode 100644 src/main/kotlin/oop/Memento/Originator.kt create mode 100644 src/test/kotlin/oop/Memento/MementoTest.kt diff --git a/README.md b/README.md index 44b0ee7..1b8451e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Kotlin OOP and FP Design Patterns * [ ] [Interpreter](#interpreter) * [ ] [Iterator](#iterator) * [ ] [Mediator](#mediator) - * [ ] [Memento](#memento) + * [x] [Memento](#memento) * [ ] [Null Object](#null-object) * [x] [Observer](#observer) * [x] [State](#state) @@ -174,12 +174,40 @@ Mediator **In progress** -Memento +[Memento](/src/main/kotlin/oop/Memento) --------- > It captures and externalizes an object's internal state so it can get back to this state later without violating encapsulation -**In progress** +### Example + +```kotlin +data class Memento(val state: T) + +class Originator(var state: T) { + fun saveToMemento() = Memento(state) + fun loadFromMemento(memento: Memento) { + state = memento.state + } +} + +class CareTaker { + val mementoList = mutableListOf>() +} +``` + +### Usage + +```kotlin +val changingClass = Originator("Hello world") +val states = CareTaker() + +changingClass.state += "!" +states.mementoList.add(changingClass.saveToMemento()) + +changingClass.state = "I've made a mistake :(" +changingClass.loadFromMemento(states.mementoList[0]) +``` Null Object ----------- diff --git a/src/main/kotlin/oop/Memento/CareTaker.kt b/src/main/kotlin/oop/Memento/CareTaker.kt new file mode 100644 index 0000000..c5b7232 --- /dev/null +++ b/src/main/kotlin/oop/Memento/CareTaker.kt @@ -0,0 +1,5 @@ +package oop.Memento + +class CareTaker { + val mementoList = mutableListOf>() +} diff --git a/src/main/kotlin/oop/Memento/Memento.kt b/src/main/kotlin/oop/Memento/Memento.kt new file mode 100644 index 0000000..9a99b72 --- /dev/null +++ b/src/main/kotlin/oop/Memento/Memento.kt @@ -0,0 +1,3 @@ +package oop.Memento + +data class Memento(val state: T) diff --git a/src/main/kotlin/oop/Memento/Originator.kt b/src/main/kotlin/oop/Memento/Originator.kt new file mode 100644 index 0000000..a0dd5cc --- /dev/null +++ b/src/main/kotlin/oop/Memento/Originator.kt @@ -0,0 +1,8 @@ +package oop.Memento + +class Originator(var state : T) { + fun saveToMemento() = Memento(state) + fun loadFromMemento(memento: Memento) { + state = memento.state + } +} diff --git a/src/test/kotlin/oop/Memento/MementoTest.kt b/src/test/kotlin/oop/Memento/MementoTest.kt new file mode 100644 index 0000000..245d445 --- /dev/null +++ b/src/test/kotlin/oop/Memento/MementoTest.kt @@ -0,0 +1,43 @@ +package oop.Memento + +import com.natpryce.hamkrest.Matcher +import com.natpryce.hamkrest.assertion.assert +import org.junit.Test + +class MementoTest { + + fun `is`(list: List): Matcher> = Matcher(List::equals, list) + fun `is`(list: Memento): Matcher> = Matcher(Memento::equals, list) + + @Test + fun `memento state should be equal to last originator state`() { + val originator = Originator(emptyList()) + originator.state = listOf(1,2,3) + + val memento = originator.saveToMemento() + + assert.that(memento.state, `is`(memento.state)) + } + + @Test + fun `originator state should be equal to last memento loaded`() { + val memento = Memento(listOf(1,2,3)) + val originator = Originator(emptyList()) + + originator.loadFromMemento(memento) + + assert.that(originator.state, `is`(memento.state)) + } + + @Test + fun `care taker should store mementos`() { + val careTaker = CareTaker>() + val originator = Originator(listOf(1,2,3)) + val memento = originator.saveToMemento() + + careTaker.mementoList.add(memento) + + assert.that(careTaker.mementoList[0], `is`(memento)) + } + +} From b74db35fbc041a226cf7a5420dc193b019768d30 Mon Sep 17 00:00:00 2001 From: Cotel Date: Mon, 1 May 2017 20:29:51 +0200 Subject: [PATCH 2/2] Fixing tests and improving CareTaker --- src/main/kotlin/oop/Memento/CareTaker.kt | 8 +++++++- src/test/kotlin/oop/Memento/MementoTest.kt | 6 +++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/oop/Memento/CareTaker.kt b/src/main/kotlin/oop/Memento/CareTaker.kt index c5b7232..9d9b66e 100644 --- a/src/main/kotlin/oop/Memento/CareTaker.kt +++ b/src/main/kotlin/oop/Memento/CareTaker.kt @@ -1,5 +1,11 @@ package oop.Memento class CareTaker { - val mementoList = mutableListOf>() + private val mementoList = mutableListOf>() + + fun addMemento(memento: Memento) { + mementoList.add(memento) + } + + fun getMemento(index: Int) : Memento? = mementoList[index] } diff --git a/src/test/kotlin/oop/Memento/MementoTest.kt b/src/test/kotlin/oop/Memento/MementoTest.kt index 245d445..d12594e 100644 --- a/src/test/kotlin/oop/Memento/MementoTest.kt +++ b/src/test/kotlin/oop/Memento/MementoTest.kt @@ -16,7 +16,7 @@ class MementoTest { val memento = originator.saveToMemento() - assert.that(memento.state, `is`(memento.state)) + assert.that(originator.state, `is`(memento.state)) } @Test @@ -35,9 +35,9 @@ class MementoTest { val originator = Originator(listOf(1,2,3)) val memento = originator.saveToMemento() - careTaker.mementoList.add(memento) + careTaker.addMemento(memento) - assert.that(careTaker.mementoList[0], `is`(memento)) + assert.that(careTaker.getMemento(0)!!, `is`(memento)) } }