はじめに
- Kotlinとポケモンで学ぶデザインパターン【第1章 Iterator】
- Kotlinとポケモンで学ぶデザインパターン【第2章 Adapter】
- Kotlinとポケモンで学ぶデザインパターン【第3章 TemplateMethod 】
第二回となります。今回はAdapterパターンを書いていきます。
【第2章 Adapter】
Adapterパターンは「すでに提供されているもの」と「必要なもの」の間の「ずれ」を埋めるようなデザインパターンです。
バージョンアップなどで機能を変更・追加する際にAdapterパターンを適用すれば既存のクラスに全く手を加えることがないため、以下のようなメリットがあります。
- 既存のクラスに対してテストを繰り返す必要が無い
- 過去バージョンとの互換性が保証される
実装
Adapterパターンを適用する設定として、第二世代(ポケモン金銀)での野生ポケモンとの遭遇について考えていきます。
初代ポケモンのときは野生ポケモンと遭遇する処理を以下のように実装しました。
open class Encount(val name: String){
fun information(): String {
return "あ! やせいの $name が とびだしてきた!"
}
}
val encount = Encount("ピカチュウ")
println(encount.information())
あ! やせいの ピカチュウ が とびだしてきた!
第二世代ではゲームボーイカラーによるカラー表現を利用した色違いポケモンや、ポケルスというウィルスに感染した野生ポケモンと極低確率で遭遇するシステムを追加します。
Encount2が第二世代に必要とされるインターフェースとします。
interface Encount2 {
fun informationBase(): String
fun informationColor(): String
fun informationPokerus(): String
}
Adapterの役割を果たすNewEncountクラスによってEncountを継承し、Encount2を実装します。
class NewEncount(name: String) : Encount(name), Encount2 {
val num = Random().nextInt(65536)
override fun informationBase(): String {
return information()
}
override fun informationColor(): String {
return if(num.rem(8192) == 0) "この $name は色違いです" else "この $name は普通の色です"
}
override fun informationPokerus(): String{
return if(num.rem(218845) == 0) "この $name はポケルスに感染しています" else "この $name はポケルスに感染していません"
}
}
val encount2 : Encount2 = NewEncount("ピチュー")
println(encount2.informationBase())
println(encount2.informationColor())
println(encount2.informationPokerus())
ここで、NewEncountのインスタンスをEncount2インターフェース型の変数に代入していることがポイント
あ! やせいの ピチュー が とびだしてきた!
この ピチュー は普通の色です
この ピチュー はポケルスに感染していません
(※野生でピチューが出現することはありません)
【Kotlin文法】if式
Kotlinにおけるifは式で、値を返します。
return if(num.rem(8192) == 0) "この $name は色違いです" else "この $name は普通の色です"
Javaならばこのようになります。
if(num % 8192 == 0) {
return "この " + name + " は色違いです"
} else {
return "この " + name + " は普通の色です"
}
三項演算子として書けますね。よく1行にまとめたがる私の好みです。
ifが式のため、Kotlinには三項演算子が存在しません。