Last active
February 16, 2019 05:31
-
-
Save nobuoka/8019bbbe3b5cf54b8d4873176b947768 to your computer and use it in GitHub Desktop.
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
// === ドメインレイヤ === | |
sealed class FizzBuzzValue { | |
abstract val expression: String | |
data class Number(override val expression: String) : FizzBuzzValue() | |
object Fizz : FizzBuzzValue() { override val expression: String = "Fizz" } | |
object Buzz : FizzBuzzValue() { override val expression: String = "Buzz" } | |
object FizzBuzz : FizzBuzzValue() { override val expression: String = "FizzBuzz" } | |
} | |
object FizzBuzzValueFactory { | |
fun create(inputNumber: Int): FizzBuzzValue = run { | |
val hasFizz = inputNumber % 3 == 0 | |
val hasBuzz = inputNumber % 5 == 0 | |
return when { | |
hasFizz && hasBuzz -> FizzBuzzValue.FizzBuzz | |
hasFizz -> FizzBuzzValue.Fizz | |
hasBuzz -> FizzBuzzValue.Buzz | |
else -> FizzBuzzValue.Number(inputNumber.toString()) | |
} | |
} | |
} | |
// === アプリケーションレイヤ === | |
/** | |
* 指定の出力先に Fizz Buzz を表示するアプリケーションサービス。 | |
* | |
* @param output 表示先に出力する処理。 Fizz Buzz の値ごとに呼ばれる。 | |
*/ | |
class ShowFizzBuzzService(private val output: (String) -> Unit) { | |
/** | |
* 指定された範囲の数値に対応する Fizz Buzz を表示する。 | |
* | |
* @param inputNumbers 対象の数値の範囲。 | |
*/ | |
operator fun invoke(inputNumbers: IntRange) { | |
inputNumbers.map(FizzBuzzValueFactory::create).map(FizzBuzzValue::expression).forEach(output) | |
} | |
} | |
// === main 関数 === | |
fun main() { | |
val showFizzBuzz = ShowFizzBuzzService(::println) | |
showFizzBuzz(1..15) | |
} |
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 FizzBuzzConfigItem( | |
/** この条件が真になる場合に [expression] が出力に含まれる。 */ | |
val predicate: (Int) -> Boolean, | |
/** 条件が真の場合に出力される文字列。 */ | |
val expression: String | |
) | |
class FizzBuzzCalculator(private val config: List<FizzBuzzConfigItem>) { | |
fun calculate(inputNumber: Int): String = run { | |
val expressions = config.filter { it.predicate(inputNumber) }.map(FizzBuzzConfigItem::expression) | |
if (expressions.isEmpty()) { | |
inputNumber.toString() | |
} else { | |
expressions.joinToString("") | |
} | |
} | |
companion object { | |
/** | |
* 3 で割り切れる場合は 「Fizz」、5 で割り切れる場合は 「Buzz」 になるインスタンス。 | |
*/ | |
val normalInstance by lazy { | |
FizzBuzzCalculator(listOf( | |
FizzBuzzConfigItem({ it % 3 == 0 }, "Fizz"), | |
FizzBuzzConfigItem({ it % 5 == 0 }, "Buzz") | |
)) | |
} | |
} | |
} | |
// === アプリケーションレイヤ === | |
/** | |
* 指定の出力先に Fizz Buzz を表示するアプリケーションサービス。 | |
* | |
* @param output 表示先に出力する処理。 Fizz Buzz の値ごとに呼ばれる。 | |
*/ | |
class ShowNormalFizzBuzzService(private val output: (String) -> Unit) { | |
/** | |
* 指定された範囲の数値に対応する Fizz Buzz を表示する。 | |
* | |
* @param inputNumbers 対象の数値の範囲。 | |
*/ | |
operator fun invoke(inputNumbers: IntRange) { | |
val calculator = FizzBuzzCalculator.normalInstance | |
inputNumbers.map(calculator::calculate).forEach(output) | |
} | |
} | |
// === main 関数 === | |
fun main() { | |
val showFizzBuzz = ShowNormalFizzBuzzService(::println) | |
showFizzBuzz(1..15) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment