1. パターンの意図
ビルダーパターン(Builder) は、複雑なオブジェクトを段階的に組み立てる仕組みを提供するデザインパターンです。
解決する問題
- コンストラクタの引数が多すぎて可読性が落ちる(テレスコーピングコンストラクタ問題)
- オプション項目が多いオブジェクトを柔軟に生成したい
- オブジェクトの組み立て過程を隠蔽しつつ、利用者にはシンプルな API を提供したい
ポイント
- 分かりやすいメソッドチェーンでオブジェクトを構築
- 必須項目と任意項目を区別できる
- 「構築の手順」と「最終製品」を分離できる
2. UML 図
3. Flutter / Dart 実装例
3.1 Product
class User {
final String name;
final int age;
final String? email;
final String? phone;
User._builder(UserBuilder builder)
: name = builder.name,
age = builder.age,
email = builder.email,
phone = builder.phone;
@override
String toString() => 'User(name: $name, age: $age, email: $email, phone: $phone)';
}
3.2 Builder
class UserBuilder {
final String name;
final int age;
String? email;
String? phone;
UserBuilder({required this.name, required this.age});
UserBuilder setEmail(String email) {
this.email = email;
return this;
}
UserBuilder setPhone(String phone) {
this.phone = phone;
return this;
}
User build() => User._builder(this);
}
3.3 利用例
void main() {
var user = UserBuilder(name: "Anna", age: 25)
.setEmail("anna@example.com")
.setPhone("123-456")
.build();
print(user);
// User(name: Anna, age: 25, email: anna@example.com, phone: 123-456)
}
4. Android / Kotlin 実装例
4.1 Product
class User private constructor(
val name: String,
val age: Int,
val email: String?,
val phone: String?
) {
class Builder(val name: String, val age: Int) {
private var email: String? = null
private var phone: String? = null
fun setEmail(email: String) = apply { this.email = email }
fun setPhone(phone: String) = apply { this.phone = phone }
fun build(): User = User(name, age, email, phone)
}
override fun toString(): String {
return "User(name=$name, age=$age, email=$email, phone=$phone)"
}
}
4.2 利用例
fun main() {
val user = User.Builder("Anna", 25)
.setEmail("anna@example.com")
.setPhone("123-456")
.build()
println(user)
}
5. メリット / デメリット
メリット
- 複雑なオブジェクト生成を分かりやすく整理できる
- 必須/任意プロパティを区別可能
- メソッドチェーンで直感的に記述できる
デメリット
- クラスが増える(Builder クラスが必要)
- シンプルなオブジェクトにはオーバーエンジニアリングになる
6. 実務ユースケース
Flutter
- ネットワークリクエスト(Dio の
RequestOptions
) - UI コンポーネントの段階的構築(Dialog, Form)
- 設定ファイルや複雑なモデル構築
Android (Kotlin)
-
AlertDialog.Builder
やNotificationCompat.Builder
- Retrofit リクエストオプション
- データクラスの段階的構築
7. 実装上の注意点
Flutter / Dart
-
必須フィールドは
UserBuilder
のコンストラクタで受け取り、任意フィールドは setter で追加する -
copyWith
と組み合わせると「ビルダー+イミュータブル」設計が可能
Android / Kotlin
- Kotlin では
data class + copy()
が強力なので、Builder は必須ではない - ただし Java 互換 API や Android 標準 API(Dialog など) では依然としてよく使われる
8. どんなときに使う?
- コンストラクタの引数が 4つ以上でオプションが多い
- オブジェクト生成を 可読性よく表現したい
- 段階的な組み立て手順を明示化したい
まとめ
- ビルダーパターンは「複雑なオブジェクトを段階的に構築する」ための仕組み
- Flutter では
Dio
リクエストや UI 構築に応用され、Android ではAlertDialog.Builder
が代表例 - 必須項目と任意項目を分けられる点が最大の強み
- Kotlin では
copy()
で代替できる場面も多いが、Java 互換性や柔軟性が求められる場合は有効