基本コンセプト
ビルダーモードは、複雑なオブジェクトの作成スキーマを作成するためのステップバイステップです。ビルドプロセスを示し、分離部材が開口するように、複雑なオブジェクトとそのコンポーネントのモデルを構築するプロセスは、切り離します。
シナリオ
- オブジェクトの作成プロセスは複雑であり、または順番や組み合わせは(あなたがGOF「デザインモード」を参照してくださいすることができます古典的なビルダーモード)の依存関係を持って作成します。
- 多くのオブジェクトを作成するために必要なパラメータ、および多くのオプションのパラメータが含まれ(バリアントビルダーモードを、あなたは、「効果的なJavaの」ビルダーの項を参照することができます)。
サンプルコード
このセクションでは、バリアントビルダーモード、次のサンプルコードを焦点:
public class RobustPerson {
// 必要参数
private final int id; // 所有属性都被final修饰
private final String name;
// 可选参数
private final int age;
private final String gender;
private final double height;
private final int weight;
private RobustPerson(Builder builder) { // 构造方法私有,即客户端不能直接创建RobustPerson对象
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
this.gender = builder.gender;
this.height = builder.height;
this.weight = builder.weight;
}
public static final class Builder {
// 必要参数
private final int id; // 必要属性被final修饰
private final String name;
// 可选参数
private int age;
private String gender;
private double height;
private int weight;
public Builder(int id, String name) { this.id = id; this.name = name; } // 必要参数通过构造方法赋值
public Builder age(int age) { this.age = age; return this; } // 可选参数通过同名方法赋值
public Builder gender(String gender) { this.gender = gender; return this; }
public Builder height(double height) { this.height = height; return this; }
public Builder weight(int weight) { this.weight = weight; return this; }
public RobustPerson build() {
RobustPerson person = new RobustPerson(this);
// 复杂业务语义校验,对于校验不通过场景,抛出异常
if (person.height != 0 && person.weight != 0) { // Builder对象并非线程安全的,不能用this.xxx校验
double bmi = person.weight / (person.height * person.height);
if (bmi < 18 || bmi > 25) { // 身体质量指数(BMI)低于18或高于25时表示不健康
throw new IllegalArgumentException(person.name+" NOT A ROBUST PERSON!");
}
}
return person;
}
}
public Builder toBuilder() { // 克隆
return new Builder(this.id, this.name).age(this.age)
.gender(this.gender).height(this.height).weight(this.weight);
}
@Override
public String toString() {
return name + "{" + "id=" + id + ", age=" + age + ", gender='" + gender + '\'' +
", height=" + height + "m, weight=" + weight + "kg}";
}
}
次のようにテストクラスは次のとおりです。
public class BuilderTest {
public static void main(String[] args) {
RobustPerson jack = new RobustPerson.Builder(1, "Jack")
.age(18).gender("male").height(1.70).weight(65).build();
System.out.println(jack);
System.out.println("Jack keeps eating too much...");
System.out.println(jack.toBuilder().weight(80).build());
}
}
出力を実行した後:
Jack{id=1, age=18, gender='male', height=1.7m, weight=65kg}
Jack keeps eating too much...
Exception in thread "main" java.lang.IllegalArgumentException: Jack NOT A ROBUST PERSON!
at builder.RobustPerson$Builder.build(RobustPerson.java:48)
at builder.BuilderTest.main(BuilderTest.java:14)
主な特徴
サンプルコードセクションを結合、オブジェクト・モデルを作成するように見えるビルダーは、以下の特性を有します。
- RobustPersonクラスのコンストラクタはプライベートですつまり、クライアントが直接RobustPersonオブジェクトを作成することはできません。
- RobustPerson不変クラス(スレッドセーフ):すべての属性は、コンストラクタで設定された最終修正、パラメータ値であり、(任意の方法ゲッター)は、外部セッターメソッドを提供しません。
- ビルダーとRobustPerson静的内部クラスのメンバ変数は、同一の建設方法、オプションのパラメータによって同じ名前の加工方法で修正されたプロセス・パラメータ必要ビルダー最終を有します。
- RobustPersonオブジェクトを作成するビルダー()メソッドの呼び出しRobustPersonプライベートコンストラクタで構築し、クライアントは、ビルド()メソッドによって(したがって無効な状態を回避する)オブジェクトを作成することができます。
- Builderオブジェクトはスレッドセーフではありません。あなたがテスト用に作成したビルド()メソッドを対応オブジェクトRobustPersonパラメータに制約を課す必要がある場合RobustPersonオブジェクト。
- 複数のオブジェクトを作成し、ほとんどの属性値が同じであるオブジェクト場合)toBuilder(によって容易にかつ効率的に複製することができる再び、異なる属性のための唯一の設定値。
- チェーン呼び出し、使用ビルダーモード可読性より良いを。
ビルダーモードだけでなく、必然的に自身の欠点。例えば:
- あなたは、オブジェクトが最初にそのビルダーを作成する必要があります作成する前に、(チェーンはターゲットクラス定義されたビルダーのコールカテゴリをモデル化することができる場合にのみ必要)メモリを消費します。
- 長いプレゼンス定型コード(又はInnerBuilderロンボクウィジェットによって自動的に生成することができる)ビルダーモード。
業界の慣行
- StringBuilder(JDK)
- JobBuilder(石英-2.3.0.jar)
- SessionFactoryBuilder等(休止コア-5.3.6.Final.jar)