[Item 2]コンストラクタに多くのパラメータがある場合は、コンストラクタを考慮してください.


静的ファクトリとジェネレータでインスタンスを作成する場合、共通の制限があります.
すなわち、オプションパラメータが多数あると、適切な応答が困難になる.
次のTimeUtilがあるとします.
次に例を示します.クラスには6つのpropertyがあり、年月1秒を表します.
このTimeUtilインスタンスを作成するには、作成するすべてのパラメータを含むコンストラクション関数から最も短いものを選択して呼び出す必要があります.
public class TimeUtil {
  private int year;
  private int month;
  private int day;
  private int hour;
  private int minute;
  private int second;

  public TimeUtil(int year, int month, int day) {
    this.year = year;
    this.month = month;
    this.day = day;
  }

  public TimeUtil(int year, int month, int day, int hour) {
    this.year = year;
    this.month = month;
    this.day = day;
    this.hour = hour;
  }

  public TimeUtil(int year, int month, int day, int hour, int minute) {
    this.year = year;
    this.month = month;
    this.day = day;
    this.hour = hour;
    this.minute = minute;
  }

  public TimeUtil(int year, int month, int day, int hour, int minute, int second) {
    this.year = year;
    this.month = month;
    this.day = day;
    this.hour = hour;
    this.minute = minute;
    this.second = second;
  }
}
年月日の秒数だけを入れたい場合は、時間と分に不要な時間0を入れます.6つのPropertyを使用してサンプルを作成することはできませんが、20個30個と考えている場合は、不要なパラメータが非常に多くなります.
TimeUtil time = new TimeUtil(2020,12,3,0,0,30);
したがって、このように数が多いと、クライアントコードの作成や読み取りが困難になる可能性があります.
パラメータが正確に個数を超えているかどうかを決定するのは難しいし、パラメータがどこに移動するかを決定するのも難しい.また、パラメータの順序が変更されると、タイプが同じであるため、実行時にサイドエフェクトが発生する可能性があります.

JavaBeansモード


JavaBeansモードは、オブジェクトを作成するときにsetterメソッドを使用して必要なパラメータ値を設定する方法で、オブジェクトはパラメータのない作成者です.前述のTimeUtilをJavaBeansモードとして表します.
public class TimeUtilJavaBeansPattern {
  private int year;
  private int month;
  private int day;
  private int hour;
  private int minute;
  private int second;

  public void setYear(int year) { this.year = year; }
  public void setMonth(int month) { this.month = month; }
  public void setDay(int day) { this.day = day; }
  public void setHour(int hour) { this.hour = hour; }
  public void setMinute(int minute) { this.minute = minute; }
  public void setSecond(int second) { this.second = second; }
}

TimeUtilJavaBeanspattern timeUtil = new TimeUtilJavaBeanspattern();
timeUtil.setYear(2020);
timeUtil.setMonth(12);
timeUtil.setDay(3);
timeUtil.setSecond(30);
しかし、上記の方法でJavaBeansモードを作成することも深刻な欠点がある.
すなわち、複数のsetterメソッドを呼び出してオブジェクトを作成し、オブジェクトを完全に作成する前にオブジェクトの一貫性がクラッシュする必要があります.
したがって、JavaBeansモードではクラスを変更することはできません.また、開発者はスレッドのセキュリティを得るために他の作業を行う必要があります.
ここでは、これらの欠点を兼ね備えたコンストラクタモードについて説明します.

ビルダアレイ


コンストラクタアレイは、ポイント積層ジェネレータアレイのセキュリティとJavaBeansアレイの読み取り可能性を兼ね備えています.
ソースコードで直接見てみましょう

public class TimeUtilBuilder {
  private final int year;
  private final int month;
  private final int day;
  private final int hour;
  private final int minute;
  private final int second;

  public TimeUtilBuilder(Builder builder) {
    this.year = builder.year;
    this.month = builder.month;
    this.day = builder.day;
    this.hour = builder.hour;
    this.minute = builder.minute;
    this.second = builder.second;
  }

  public static class Builder{
    private int year;
    private int month;
    private int day;
    private int hour;
    private int minute;
    private int second;

    public Builder year(int year) {
      this.year = year;
      return this;
    }

    public Builder month(int month) {
      this.month = month;
      return this;
    }

    ...

    public TimeUtilBuilder build() {
      return new TimeUtilBuilder(this);
    }
  }
}
コンストラクタモードでコンストラクタオブジェクトを取得し、必要なオブジェクトを直接作成するのではなく、コンストラクタオブジェクトが提供するsetterメソッドでパラメータ値を設定します.
次に、build()メソッドを呼び出して、使用するTimeUtilBuilderオブジェクトを取得します.これにより、ポイント積層パターンとJavaBeansパターンを使用したように、オブジェクトの不変性が確保されます.
コードは書きやすく、読みやすさが向上します.
new TimeUtilBuilder.Builder()
    .year(2020)
    .month(12)
    .day(3)
    .build();
しかし、これらのコンストラクタモードは必ずしも唯一の利点ではありません.これは、オブジェクトを作成するには、まずコンストラクタを作成する必要があります.コンストラクタを作成するコストは高くありませんが、パフォーマンスが敏感な場合は問題になる可能性があります.これは、値を割り当てるには4つ以上のパラメータが必要だからです.
時間が経つにつれて、APIのパラメータはますます多くなるので、状況に応じて使用することができます.
本の中にはピザを例にしたビルド柄の例がありますが、スキップしましょう.