導入
コンストラクタの引数が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) を外すとどう変わるか試してみてください。
演習
BurgerBuilder に setTomato(boolean tomato) を追加し(Burger にも boolean tomato フィールドを追加)、show() で tomato が true のとき " + トマト" を付け加えるようにしてください。main で new BurgerBuilder().setPatty("チキン").setLettuce(true).setTomato(true).build() を作って show() してください。
ヒント1を見る
Burger に boolean tomato; を追加し、show() に if (tomato) { s += " + トマト"; } を足します。
ヒント2を見る
BurgerBuilder に BurgerBuilder setTomato(boolean tomato) { burger.tomato = tomato; return this; } を追加します。