1.はじめに

この簡単な記事では、KotlinでBuilderデザインパターンを実装する方法について説明します。

2.ビルダーパターン

ビルダーパターンは、人々がよく使用するものですが、自分自身で作成することはめったにありません。

たくさんのパラメータを含む可能性のあるオブジェクトの構築や、オブジェクトの構築が完了したときにそのオブジェクトを不変にしたい場合は、処理するのが素晴らしいです。

詳細については、Creational Design Patterns

ここ

のチュートリアルをご覧ください。

3.実装

Kotlinは、名前付きおよびデフォルトのパラメータ、

apply()

、および

data class

など、多くの便利な機能を提供します。これにより、古典的なBuilderパターン実装は使用されません。

そのため、最初に古典的なJavaスタイルの実装を見てから、さらにKotlinスタイルの短縮形を見ていきます。

[[java style]]

3.1. Javaスタイルの実装

外部オブジェクトから直接アクセスしたくないため、読み取り専用フィールドを含む

FoodOrder

という1つのクラスの作成を始めましょう。

class FoodOrder private constructor(builder: FoodOrder.Builder) {

    val bread: String?
    val condiments: String?
    val meat: String?
    val fish: String?

    init {
        this.bread = builder.bread
        this.condiments = builder.condiments
        this.meat = builder.meat
        this.fish = builder.fish
    }

    class Builder {
       //builder code
    }
}

  • コンストラクタは

    private

    なので、ネストされた

    Builder

    クラスだけがアクセスできます。

それでは、オブジェクトの構築に使用されるネストクラスの作成に移りましょう。

class Builder {

    var bread: String? = null
      private set
    var condiments: String? = null
      private set
    var meat: String? = null
      private set
    var fish: String? = null
      private set

    fun bread(bread: String) = apply { this.bread = bread }
    fun condiments(condiments: String) = apply { this.condiments = condiments }
    fun meat(meat: String) = apply { this.meat = meat }
    fun fish(fish: String) = apply { this.fish = fish }
    fun build() = FoodOrder(this)
}

見てのとおり、**

Builder

には外部クラスと同じフィールドがあります。各外部フィールドに対して、対応する設定メソッドがあります。

設定メソッドを使用する代わりに、1つ以上の必須フィールドがある場合は、コンストラクタにそれらを設定させてみましょう。


https://en.wikipedia.org/wiki/Fluent


interface[流れるようなデザイン]のアプローチをサポートするために

apply__関数を使用していることに注意してください。

最後に、

build

メソッドを使用して、

FoodOrder

コンストラクタを呼び出します。

3.2. ケルティンスタイルの実装

Kotlinを最大限に活用するためには、Javaで慣れ親しんだベストプラクティスをいくつか見直す必要があります。それらの多くはより良い代替手段に置き換えることができます。

慣用的なKotlinコードを書く方法を見てみましょう。

class FoodOrder(
  val bread: String?,
  val condiments: String?,
  val meat: String?,
  val fish: String?) {

    data class Builder(
      var bread: String? = null,
      var condiments: String? = null,
      var meat: String? = null,
      var fish: String? = null) {

        fun bread(bread: String) = apply { this.bread = bread
        fun condiments(condiments: String) = apply { this.condiments = condiments }
        fun meat(meat: String) = apply { this.meat = meat }
        fun fish(fish: String) = apply { this.fish = fish }
        fun build() = FoodOrder(bread, condiments, meat, fish)
    }
}

  • Kotlinには、オーバーロードの数を最小限に抑え、関数呼び出しの読みやすさを向上させるのに役立つ名前付きおよびデフォルトのパラメータが付属しています。

Kotlinのデータクラス構造を利用することもできます。これについては、別のチュートリアルhttps://www.baeldung.com/kotlin-data-classes[here]を参照してください。

最後に、Javaスタイルの実装と同様に、

apply()

は流暢なセッターの実装に役立ちます。

4.使用例

簡単に言えば、これらのBuilderパターン実装を使用して

FoodOrder

オブジェクトを構築する方法を見てみましょう。

val foodOrder = FoodOrder.Builder()
  .bread("white bread")
  .meat("bacon")
  .condiments("olive oil")
  .build()

5.まとめ

ビルダーパターンは、多くのコンストラクタを書かずに不変オブジェクトを柔軟に作成する方法に関するオブジェクト指向プログラミングの非常に一般的な問題を解決します。

建築者を考えるとき、私達は構造が複雑であるかどうかに焦点を合わせるべきである。単純な構成パターンがある場合は、柔軟なビルダーオブジェクトを作成することで得られる成果が恩恵をはるかに超える可能性があります。

いつものように、このコードはhttps://github.com/eugenp/tutorials/tree/master/core-kotlin[Githubで利用可能]です。