本文へスキップ
BecomeCoder

Javaデザインパターンコース · 第2章 生成に関するパターン ― オブジェクトの「作り方」を工夫する · レッスン5

Builder ― 複雑な組み立て手順を読みやすくする

ブラウザで完結

導入

コンストラクタの引数が5個も6個もあると、new Burger("ビーフ", true, false, true, false, ...) のように、どの true/false が何を意味するのか読み取れなくなります。Builder(ビルダー) パターンは、部品を1つずつ名前つきで積み上げて、最後にまとめて組み立てる型です。

説明

Builderは「組み立て中の一時的な入れ物(Builder)」を用意し、設定用メソッドが自分自身(this)を返すことで、メソッドを . でつなげて書けるようにします(メソッドチェーン)。

public class Main {
    public static void main(String[] args) {
        Burger burger = new BurgerBuilder()
            .setPatty("ビーフ")
            .setCheese(true)
            .setLettuce(true)
            .build();
        burger.show();
    }
}

class Burger {
    String patty;
    boolean cheese;
    boolean lettuce;

    void show() {
        String s = patty + "パティ";
        if (cheese) {
            s += " + チーズ";
        }
        if (lettuce) {
            s += " + レタス";
        }
        System.out.println(s);
    }
}

class BurgerBuilder {
    private Burger burger = new Burger();

    BurgerBuilder setPatty(String patty) {
        burger.patty = patty;
        return this;
    }

    BurgerBuilder setCheese(boolean cheese) {
        burger.cheese = cheese;
        return this;
    }

    BurgerBuilder setLettuce(boolean lettuce) {
        burger.lettuce = lettuce;
        return this;
    }

    Burger build() {
        return burger;
    }
}
classDiagram
  BurgerBuilder ..> Burger : builds
  class BurgerBuilder {
    -Burger burger
    +setPatty(patty) BurgerBuilder
    +setCheese(cheese) BurgerBuilder
    +setLettuce(lettuce) BurgerBuilder
    +build() Burger
  }
  • setPatty(...) { ...; return this; } … 設定したあと this(自分自身)を返す のがポイントです。これにより戻り値に対してさらに .setCheese(...) を呼べます。
  • new BurgerBuilder().setPatty(...).setCheese(...).setLettuce(...).build() … 1本のメソッドチェーンとして、必要な項目だけを名前つきで設定できます。setCheese を省略すれば cheese は初期値の false のままです。
  • 最後の build() で、組み立てた Burger を取り出します。

やってみよう

下のエディタを実行し、チーズとレタス入りのハンバーガーが正しく表示されることを確認しましょう。.setCheese(true) を外すとどう変わるか試してみてください。

演習

BurgerBuildersetTomato(boolean tomato) を追加し(Burger にも boolean tomato フィールドを追加)、show()tomatotrue のとき " + トマト" を付け加えるようにしてください。mainnew BurgerBuilder().setPatty("チキン").setLettuce(true).setTomato(true).build() を作って show() してください。

ヒント1を見る

Burgerboolean tomato; を追加し、show()if (tomato) { s += " + トマト"; } を足します。

ヒント2を見る

BurgerBuilderBurgerBuilder setTomato(boolean tomato) { burger.tomato = tomato; return this; } を追加します。

実際に動かしてみよう

下のエディタにJavaを書いて「実行」を押すと、学習用シミュレータが System.out.println の出力を表示します(本物のJVMではなく、教材の範囲を再現した軽量エンジンです)。クラス・継承・コレクションなども動きます。Scanner で入力を読む例は「標準入力」欄に値を入れてください。本文の例を書き換えて動かしてみましょう(Stream・ラムダ・スレッド・ファイル入出力など一部の機能は対象外です)。

Java — ブラウザ内で実行(学習用シミュレータ)

Javaの教材サブセットを動かす学習用シミュレータを読み込みます(本物のJVMではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。