[パーフェクトjava]アイテム2コンストラクション関数に多くのパラメータがある場合は、コンストラクタを考慮します.


パラメータが多ければ多いほど、クライアントコードの作成や読み取りが難しくなります.コードを読むときは、各値の意味を混同し、数パラメータがどれだけあるかに注意します.
JavaBeansモード(パラメータレスジェネレータを使用してオブジェクトを作成し、setterメソッドを呼び出して必要なパラメータの値を設定)
->欠点:オブジェクトを作成するには、複数のメソッドを呼び出し、オブジェクトを完全に作成する前にコンシステンシがクラッシュします.

Builderモードビルダーモード

  • クライアントは、必要なオブジェクトを直接作成するのではなく、必要なパラメータを呼び出してコンストラクタオブジェクトを取得します.次にsetterメソッドを使用して、必要な選択パラメータを設定します.
  • これは
  • (PythonとScaraにある)の名前を模したオプションのパラメータです.
  • 階層設計のクラスと一緒に使用するのに適しています.

  • 次はPizzaの抽象レベルを継承したNyPizza(ニューヨークピザ)とCalzone(カルチョネピザ)のレベル構造図です.
    NyPizzaはsizeという値を受け入れる必要があります.CalzoneはsauseInsideというブール値でソースコードを入れるかどうかを選択できます.
    public abstract class Pizza{
       public enum Topping { HAM, MUSHROOM, ONION, PEPPER, SAUSAGE }
       final Set<Topping> toppings;
    
       abstract static class Builder<T extends Builder<T>> {
          EnumSet<Topping> toppings = EnumSet.noneOf(Topping.class);
          public T addTopping(Topping topping) {
             toppings.add(Objects.requireNonNull(topping));
             return self();
          }
    
          abstract Pizza build();
    
          protected abstract T self();
       }
    
       Pizza(Builder<?> builder) {
          toppings = builder.toppings.clone();
       }
    }
    さらにselfの抽象手法を加えることで,サブクラスで変換する必要がなく,メソッドの体化を可能にする.
    public class NyPizza extends Pizza {
       public enum Size { SMALL, MEDIUM, LARGE }
       private final Size size;
    
       public static class Builder extends Pizza.Builder<Builder> {
          private final Size size;
    
          public Builder(Size size) {
             this.size = Objects.requireNonNull(size);
          }
    
          @Override public NyPizza build() {
             return new NyPizza(this);
          }
    
          @Override protected Builder self() { return this; }
       }
    
       private NyPizza(Builder builder) {
          super(builder);
          size = builder.size;
       }
    }
    public class Calzone extends Pizza {
       private final boolean sauceInside;
    
       public static class Builder extends Pizza.Builder<Builder> {
          private boolean sauceInside = false;
    
          public Builder sauceInside() {
             sauceInside = true;
             return this;
          }
    
          @Override public Calzone build() {
             return new Calzone(this);
          }
    
          @Override protected Builder self() { return this; }
       }
    
       private Calzone(Builder builder) {
          super(builder);
          sauceInside = builder.sauceInside;
       }
    }
    各継承クラス(NyPizza,Calzone)は、親クラス(Pizza)のselfメソッドを義務的に上書きしなければならない.
    NyPizza pizza =  new NyPizza.Builder(SMALL)
          .addTopping(SAUSAGE).addTopping(ONION).build();
    Calzone calzone = new Calzone.Builder()
          .addTopping(HAM).sauceInside().build();

    コンストラクタモードの利点

  • の各因子がどういう意味か分かりやすい.
  • の一貫性を維持することができる.
  • 1つの
  • コンストラクタを使用して複数のオブジェクト間をループ作成するか、コンストラクタに渡されたパラメータに基づいて他のオブジェクトを作成できます.