四畳半の秘密基地

さあ、今日はどんな実験をしよう

MENU

Kotlinとスプラトゥーンで学ぶデザインパターン【7. Builder】

休日にやりたいことがありすぎてなかなかブログを更新できてません。
気がついてたら半年ぶりの更新になってた。
スプラトゥーン2は地味に続けてますが最近はNine Parchmentsにはまってます。

ec.nintendo.com

Builder パターンとは

普段Androidアプリの開発をしているとBuilderパターンで書かれているクラスをよく見ます。
StringBuilderとかOkHttpClientとか。
Builderパターンは複雑な処理を、段階的に組み上げていくパターンです。
また組み上げ方は固定ですが、組み上げる時に使用するオブジェクトは柔軟に変えられるようになってます。

実装

メインとなるクラスはDirectorとBuilderで、この2クラスで組み上げ方を決めています。

Director.kt

class Director(private val builder: MainWeaponBuilder) {
    fun construct() {
        builder.name(".96ガロン")
        builder.power(62)
        builder.range(31)
        builder.quickness(10)
    }
}

MainWeaponBuilder.kt

abstract class MainWeaponBuilder {
    abstract fun name(name: String)
    abstract fun range(range: Int)
    abstract fun power(power: Int)
    abstract fun quickness(quickness: Int)
}

今回はスプラトゥーン熱が低かったせいか例があまり良くないですがDirectorクラスは.96ガロンを作成するクラスとなっています。
デコるかどうかは使用するBuilderクラスに寄ります。
無印を作りたい場合はUnmarkedWeaponBuilderを、デコを作りたい場合はDecoratorWeaponBuilderを使用すれば作成できます。

UnmarkedWeaponBuilder.kt

class UnmarkedWeaponBuilder : MainWeaponBuilder() {

    var name: String? = null
    var range: Int = 0
    var power: Int = 0
    var quickness: Int = 0

    override fun name(name: String) {
        this.name = name
    }

    override fun range(range: Int) {
        this.range = range
    }

    override fun power(power: Int) {
        this.power = power
    }

    override fun quickness(quickness: Int) {
        this.quickness = quickness
    }

    fun getResult(): Weapon {
        return Weapon(name!!, range, power, quickness)
    }
}

DecoratorWeaponBuilder.kt

class DecoratorWeaponBuilder : MainWeaponBuilder() {

    var name: String? = null
    var range: Int = 0
    var power: Int = 0
    var quickness: Int = 0

    override fun name(name: String) {
        this.name = "${name}デコ"
    }

    override fun range(range: Int) {
        this.range = range
    }

    override fun power(power: Int) {
        this.power = power
    }

    override fun quickness(quickness: Int) {
        this.quickness = quickness
    }

    fun getResult(): Weapon {
        return Weapon(name!!, range, power, quickness)
    }
}

改めて見ても例がいまいち・・・。

実行結果

それぞれの.96ガロンを作成して見ます。

Main.kt

fun main(args: Array<String>) {
    val unmarkedBuilder = UnmarkedWeaponBuilder()
    var director = Director(unmarkedBuilder)
    director.construct()
    println(unmarkedBuilder.getResult())

    val decoratorBuilder = DecoratorWeaponBuilder()
    director = Director(decoratorBuilder)
    director.construct()
    println(decoratorBuilder.getResult())
}

結果は

Weapon(name=.96ガロン, range=31, power=62, quickness=10)
Weapon(name=.96ガロンデコ, range=31, power=62, quickness=10)



感想

Builderパターンというデザインパターンは1つですが、その中身は参考書籍やサイト・実際に業務で使用するクラスによってまちまちでなんとも捉え難いパターンでした。
OkHttpClintの場合は、メソッドチェーンにしてクラスで使用するパラメータを順々に渡していくやり方で自分はそれがBuilderパターンなのかと思ってました。
必要なオブジェクトを段階を踏んで組み上げることがBuilderパターンの本質で実装はそれぞれ考えてるのかなぁ。

ソースはこちら