[解決済み] Java Builder クラスのサブクラス化
2022-05-31 12:52:52
質問
与える このDr.Dobbsの記事 そして特に Builder パターンでは、Builder をサブクラス化する場合をどのように処理するのでしょうか。GMOラベルを追加するためにサブクラスを作成する例を縮小して考えると、素朴な実装は次のようになります。
public class NutritionFacts {
private final int calories;
public static class Builder {
private int calories = 0;
public Builder() {}
public Builder calories(int val) { calories = val; return this; }
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder builder) {
calories = builder.calories;
}
}
サブクラスです。
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) { hasGMO = val; return this; }
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
これで、次のようなコードが書けるようになりました。
GMOFacts.Builder b = new GMOFacts.Builder();
b.GMO(true).calories(100);
しかし、順番を間違えると全て失敗してしまいます。
GMOFacts.Builder b = new GMOFacts.Builder();
b.calories(100).GMO(true);
問題は、当然ながら
NutritionFacts.Builder
が返す
NutritionFacts.Builder
ではなく
GMOFacts.Builder
この問題をどのように解決すればよいのでしょうか、あるいはもっとよいパターンがあるのでしょうか?
注意してください。 同様の質問に対するこの回答 は、私が上に持っているクラスを提供します。私の質問は、ビルダーの呼び出しが正しい順序であることを保証する問題に関してです。
どのように解決するのですか?
ジェネリックスを使って解決できます。というものだと思います。 "不思議なほど繰り返されるジェネリックパターン"
基底クラスビルダのメソッドの戻り値の型をジェネリックの引数にする。
public class NutritionFacts {
private final int calories;
public static class Builder<T extends Builder<T>> {
private int calories = 0;
public Builder() {}
public T calories(int val) {
calories = val;
return (T) this;
}
public NutritionFacts build() { return new NutritionFacts(this); }
}
protected NutritionFacts(Builder<?> builder) {
calories = builder.calories;
}
}
ここで、派生クラスビルダを総称引数としてベースビルダのインスタンスを作成します。
public class GMOFacts extends NutritionFacts {
private final boolean hasGMO;
public static class Builder extends NutritionFacts.Builder<Builder> {
private boolean hasGMO = false;
public Builder() {}
public Builder GMO(boolean val) {
hasGMO = val;
return this;
}
public GMOFacts build() { return new GMOFacts(this); }
}
protected GMOFacts(Builder builder) {
super(builder);
hasGMO = builder.hasGMO;
}
}
関連
-
Eclipseで "XXXX "の解決策を(型に)解決することができない
-
Java(1)仕上げの基本概念+eclipseのインストール構成
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaでNullPointerExceptionを回避する方法
-
[解決済み] JavaにおけるHashMapとHashtableの違いは何ですか?
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] Javaでメモリーリークを発生させるにはどうしたらいいですか?
-
[解決済み] JavaでArrayListではなくLinkedListを使用するのはいつですか?
-
[解決済み] Java内部クラスと静的ネストされたクラス
-
[解決済み] 静的クラスとシングルトンパターンの違い?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
プロローグでのコンテンツは禁止されています
-
Spring boot runs with Error creating bean with name 'entityManagerFactory' defined in class path resource
-
node js npm gruntインストール、elasticsearch-head 5.Xインストール
-
HttpClientがGZIP形式でない場合の対処法
-
起動時にEclipseエラーが発生しました。起動中に内部エラーが発生しました。java.lang.NullPoin: "Javaツーリングの初期化 "中に内部エラーが発生しました。
-
IDEA パッケージステートメントの欠落
-
このラインで複数のマーカーを解決する方法
-
テストが見つかりませんでした
-
ローカルリソースのロードが許可されていない場合の解決策
-
Maven Pluginの実行がライフサイクル設定の対象外であるエラーの解決