LoginSignup
3
4

More than 5 years have passed since last update.

Kotlinとポケモンで学ぶデザインパターン【第3章 TemplateMethod 】

Last updated at Posted at 2018-09-17

はじめに

  1. Kotlinとポケモンで学ぶデザインパターン【第1章 Iterator】
  2. Kotlinとポケモンで学ぶデザインパターン【第2章 Adapter】
  3. Kotlinとポケモンで学ぶデザインパターン【第3章 TemplateMethod 】

第三回となります。今回はTemplateMethodパターンを書いていきます。

【第3章 TemplateMethod 】

TemplateMethodパターンは、文字通りテンプレートの機能を持つパターンです。
大まかな流れとしては、スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を定めることになります。
TemplateMethodパターンを適用するメリットは以下のようになります。

  • 一連の処理の手続きを関数にまとめることが出来るので、関数の抽象度が高まる
  • 関数を継承によって差し替えるだけでいいので、拡張性が高まる

実装

今回はTemplateMethodパターンを適用してモンスターボールを投げてポケモンをゲットする流れをまとめます。
まず、ポケモンと遭遇し、ボールを投げて、結果を表示する。という処理を抽象化した抽象クラスを作ります。
AbstractCaptureクラスでは、encount, ballThrow, resultメソッドが実体のない抽象クラスとなり、抽象メソッドを使っているcaptureがテンプレートメソッドとなります。

AbstractCapture.kt
abstract class AbstractCapture {
    abstract fun encount(pokemon: Pokemon)
    abstract fun ballThrow()
    abstract fun result(pokemon: Pokemon)

    fun capture(pokemon: Pokemon) {
        encount(pokemon)
        ballThrow()
        result(pokemon)
    }
}

ポケモンを表すデータクラス

Pokemon.kt
data class Pokemon(val name: String)

野生のポケモンを捕まえる具象クラス

WildCapture.kt
class WildCapture: AbstractCapture() {
    override fun encount(pokemon: Pokemon){
        println("あ! やせいの\n${pokemon.name}が とびだしてきた!")
    }

    override fun ballThrow(){
        println("レッドは モンスターボールを なげた!")
    }

    override fun result(pokemon: Pokemon) {
        val num = Random().nextInt(2)
        println(if(num == 0) "やったー!\n${pokemon.name}を つかまえたぞ!" else "ああ!\nつかまえたと おもったのに!")
    }
}

人のポケモンを捕まえる具象クラス

TrainerCapture.kt
class TrainerCapture: AbstractCapture() {
    override fun encount(pokemon: Pokemon){
        println("あいては\n${pokemon.name}を くりだした!")
    }

    override fun ballThrow(){
        println("レッドは マスターボールを なげた!")
    }

    override fun result(pokemon: Pokemon) {
        println("トレーナーに ボールを はじかれた!")
        println("ひとの ものを とったら どろぼう!")
    }
}

抽象クラス型の変数に具象クラスのインスタンスを代入し、テンプレートメソッドを呼び出します。

MainActivity.kt
val pikachu = Pokemon("ピカチュウ")

val wild: AbstractCapture = WildCapture()
wild.capture(pikachu)

val trainer: AbstractCapture = TrainerCapture()
trainer.capture(pikachu)
実行結果
あ! やせいの 
ピカチュウが とびだしてきた!
レッドは モンスターボールを なげた!
やったー!
ピカチュウを つかまえたぞ!

あいては
ピカチュウを くりだした!
レッドは マスターボールを なげた!
トレーナーに ボールを はじかれた!
ひとの ものを とったら どろぼう!

1回しか見たことないはずなのに記憶にずっと残ってます。

【Kotlin文法】式展開

Kotlinは文字列中に$で変数が、${}で式が書けます。

Kotlin
fun encount(pokemon: Pokemon){
    println("あ! やせいの\n${pokemon.name}が とびだしてきた!")
}

Javaならばこう

Java
void encount(Pokemon pokemon){
    System.out.println("あ! やせいの\n" + pokemon.name + "が とびだしてきた!")
}

変数使ってSQLをベタ書きする時とかに式展開できる言語だと凄い楽ですね。
ちなみにRubyの式展開は#{}です。

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4