Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flyweight #28

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/main/kotlin/oop/Flyweight/Flyweight.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package oop.Flyweight

fun main(args: Array<String>) {
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)
}
47 changes: 47 additions & 0 deletions src/main/kotlin/oop/Flyweight/Soldier.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package oop.Flyweight

data class Point(val x: Int, val y: Int)

data class Soldier(val name: String)

class Flyweight<A>(val values: MutableSet<A> = mutableSetOf()) {

fun getFactory(value: A): A {
values.add(value)
return values.filter { it == value }.first()
}

}

class SoldierFactory(val soldiers: Flyweight<Soldier> = Flyweight<Soldier>(),
val points: Flyweight<Point> = Flyweight<Point>()) {

constructor(soldiers: List<Soldier> = emptyList(), points: List<Point> = 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<Attack> = mutableListOf<Attack>()) {

fun attack(soldierName: String, x: Int, y: Int) {
val soldier = soldierFactory.getSoldier(soldierName)
val point = soldierFactory.getPoint(x, y)
attacks.add(Attack(soldier, point))
}

}
57 changes: 57 additions & 0 deletions src/test/kotlin/oop/Flyweigth/FlyweightPatternShould.kt
Original file line number Diff line number Diff line change
@@ -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<Soldier>()
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<Soldier>()
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<Soldier>())
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<Point> = Flyweight<Point>()
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))
}
}