はじめに
- Kotlinとポケモンで学ぶデザインパターン【第1章 Iterator】
- Kotlinとポケモンで学ぶデザインパターン【第2章 Adapter】
- Kotlinとポケモンで学ぶデザインパターン【第3章 TemplateMethod 】
第三回となります。今回はTemplateMethodパターンを書いていきます。
#【第3章 TemplateMethod 】
TemplateMethodパターンは、文字通りテンプレートの機能を持つパターンです。
大まかな流れとしては、スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を定めることになります。
TemplateMethodパターンを適用するメリットは以下のようになります。
- 一連の処理の手続きを関数にまとめることが出来るので、関数の抽象度が高まる
- 関数を継承によって差し替えるだけでいいので、拡張性が高まる
実装
今回はTemplateMethodパターンを適用してモンスターボールを投げてポケモンをゲットする流れをまとめます。
まず、ポケモンと遭遇し、ボールを投げて、結果を表示する。という処理を抽象化した抽象クラスを作ります。
AbstractCaptureクラスでは、encount, ballThrow, resultメソッドが実体のない抽象クラスとなり、抽象メソッドを使っているcaptureがテンプレートメソッドとなります。
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)
}
}
ポケモンを表すデータクラス
data class Pokemon(val name: String)
野生のポケモンを捕まえる具象クラス
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つかまえたと おもったのに!")
}
}
人のポケモンを捕まえる具象クラス
class TrainerCapture: AbstractCapture() {
override fun encount(pokemon: Pokemon){
println("あいては\n${pokemon.name}を くりだした!")
}
override fun ballThrow(){
println("レッドは マスターボールを なげた!")
}
override fun result(pokemon: Pokemon) {
println("トレーナーに ボールを はじかれた!")
println("ひとの ものを とったら どろぼう!")
}
}
抽象クラス型の変数に具象クラスのインスタンスを代入し、テンプレートメソッドを呼び出します。
val pikachu = Pokemon("ピカチュウ")
val wild: AbstractCapture = WildCapture()
wild.capture(pikachu)
val trainer: AbstractCapture = TrainerCapture()
trainer.capture(pikachu)
あ! やせいの
ピカチュウが とびだしてきた!
レッドは モンスターボールを なげた!
やったー!
ピカチュウを つかまえたぞ!
あいては
ピカチュウを くりだした!
レッドは マスターボールを なげた!
トレーナーに ボールを はじかれた!
ひとの ものを とったら どろぼう!
1回しか見たことないはずなのに記憶にずっと残ってます。
#【Kotlin文法】式展開
Kotlinは文字列中に$
で変数が、${}
で式が書けます。
fun encount(pokemon: Pokemon){
println("あ! やせいの\n${pokemon.name}が とびだしてきた!")
}
Javaならばこう
void encount(Pokemon pokemon){
System.out.println("あ! やせいの\n" + pokemon.name + "が とびだしてきた!")
}
変数使ってSQLをベタ書きする時とかに式展開できる言語だと凄い楽ですね。
ちなみにRubyの式展開は#{}
です。