diff --git a/src/main/kotlin/oop/Flyweight/Flyweight.kt b/src/main/kotlin/oop/Flyweight/Flyweight.kt new file mode 100644 index 0000000..0d0e8bc --- /dev/null +++ b/src/main/kotlin/oop/Flyweight/Flyweight.kt @@ -0,0 +1,20 @@ +package oop.Flyweight + +fun main(args: Array) { + val soldiers = mutableListOf( + Soldier("Pedro"), + Soldier("Ryan"), + Soldier("Forest") + ) + + val soldiersAttacks = SoldierClient(SoldierFactory(soldiers)) + soldiersAttacks.attack("Pedro", 1, 2) + soldiersAttacks.attack("Ryan", 10, 12) + soldiersAttacks.attack("Ryan", 13, 2) + soldiersAttacks.attack("Forest", 1, 2) + soldiersAttacks.attack("Pedro", 1, 2) + soldiersAttacks.attack("Pedro", 10, 12) + soldiersAttacks.attack("Pedro", 44, 5) + + soldiersAttacks.attacks.forEach(::println) +} diff --git a/src/main/kotlin/oop/Flyweight/Soldier.kt b/src/main/kotlin/oop/Flyweight/Soldier.kt new file mode 100644 index 0000000..69b8eae --- /dev/null +++ b/src/main/kotlin/oop/Flyweight/Soldier.kt @@ -0,0 +1,47 @@ +package oop.Flyweight + +data class Point(val x: Int, val y: Int) + +data class Soldier(val name: String) + +class Flyweight(val values: MutableSet = mutableSetOf()) { + + fun getFactory(value: A): A { + values.add(value) + return values.filter { it == value }.first() + } + +} + +class SoldierFactory(val soldiers: Flyweight = Flyweight(), + val points: Flyweight = Flyweight()) { + + constructor(soldiers: List = emptyList(), points: List = emptyList()) + : this(Flyweight(soldiers.toMutableSet()), Flyweight(points.toMutableSet())) + + fun getSoldier(name: String): Soldier { + return soldiers.getFactory(Soldier(name)) + } + + fun getPoint(x: Int, y: Int): Point { + return points.getFactory(Point(x, y)) + } + +} + +data class Attack(val soldier: Soldier, val point: Point) { + override fun toString(): String { + return "$soldier attack ${point.x},${point.y} point" + } +} + +class SoldierClient(private val soldierFactory: SoldierFactory, + val attacks: MutableList = mutableListOf()) { + + fun attack(soldierName: String, x: Int, y: Int) { + val soldier = soldierFactory.getSoldier(soldierName) + val point = soldierFactory.getPoint(x, y) + attacks.add(Attack(soldier, point)) + } + +} diff --git a/src/test/kotlin/oop/Flyweigth/FlyweightPatternShould.kt b/src/test/kotlin/oop/Flyweigth/FlyweightPatternShould.kt new file mode 100644 index 0000000..374400c --- /dev/null +++ b/src/test/kotlin/oop/Flyweigth/FlyweightPatternShould.kt @@ -0,0 +1,57 @@ +package oop.Flyweigth + +import junit.framework.Assert.assertTrue +import oop.Flyweight.* +import org.hamcrest.CoreMatchers.`is` +import org.hamcrest.MatcherAssert.assertThat +import org.junit.Before +import org.junit.Test +import java.util.* + +class FlyweightPatternShould { + + @Test + fun `Have one instance when only one type of soldier is created`() { + val flyweight = Flyweight() + val soldiersAttack = SoldierClient(SoldierFactory(flyweight)) + + soldiersAttack.attack("Pedro", 1, 2) + soldiersAttack.attack("Pedro", 2, 2) + soldiersAttack.attack("Pedro", 2, 2) + + assertThat(flyweight.values.filter { it.name == "Pedro" }.size, `is`(1)) + } + + @Test + fun `Have two instances when both types are created, no matter the number of soldiers`() { + val flyweight = Flyweight() + val soldierFactory = SoldierFactory(flyweight) + (1..1000).forEach { + soldierFactory.getSoldier("Pedro") + soldierFactory.getSoldier("Ryan") + } + + assertThat(flyweight.values.size, `is`(2)) + } + + @Test + fun `Have the same main object in two instances of the same type`() { + val soldierFactory = SoldierFactory(Flyweight()) + val soldierOne = soldierFactory.getSoldier("Pedro") + val soldierTwo = soldierFactory.getSoldier("Pedro") + + assertTrue(soldierOne === soldierTwo) + } + + @Test + fun `Have one instance of points when only one instance of point is created`() { + val points :Flyweight = Flyweight() + val soldiersAttack = SoldierClient(SoldierFactory(points = points)) + + soldiersAttack.attack("Pedro", 3, 3) + soldiersAttack.attack("Forest", 3, 3) + soldiersAttack.attack("Forest", 3, 3) + + assertThat(points.values.size, `is`(1)) + } +}