先日、「SetterとBuilderはどのように使いわければいいのか?」という質問を受けました。なかなかよい質問ですね。Builderを使うとクラスのインスタンスを柔軟に作ることができます。Builderを使ったサンプルコードです。
1 2 3 4
| User user = User.builder() .lastName("山田") .firstName("太郎") .build();
|
Builderを実装したUserクラスのサンプルコードです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class User { private final String lastName; private final String firstName;
User(String lastName, String firstName) { this.lastName = lastName; this.firstName = firstName; }
public static UserBuilder builder() { return new UserBuilder(); }
public static class UserBuilder { private String lastName; private String firstName;
UserBuilder() { }
public UserBuilder lastName(String lastName) { this.lastName = lastName; return this; }
public UserBuilder firstName(String firstName) { this.firstName = firstName; return this; }
public User build() { return new User(lastName, firstName); } } }
|
Setterを使うと次のようになります(実装は省略)。
1 2 3
| User user = new User(); user.setLastName("山田"); user.setFirstName("太郎");
|
Setterの問題点として、インスタンスの状態を変更してしまうことがあります。イミュータブルな実装にする場合、原則としてコンストラクタで値は設定するべきでSetterで変更するべきではありません。
では、Setterではなくコンストラクタで設定するようにしましょう。引数が少ないうちは問題がないのですが、次の例のように引数の数が増えてしまうとコードが煩雑になってしまいます。
1 2 3
|
User user = new User("山田", "太郎", null, null, "日本");
|
そこで、Builderを使うメリットが出てきます。Builderを使えば柔軟にパラメーターの設定が行えるようになります。
1 2 3 4 5
| User user = User.builder() .lastName("山田") .firstName("太郎") .country("日本") .build();
|
SetterもBuilderもやりたいことはオブジェクトにパラメーターをセットすることです。Setterを使うとオブジェクトの状態を変更してしまうことになります。イミュータブルな実装かつ柔軟にパラメーターを設定したい場合はBuilderを使いましょう。