-3

Ruby (Rails) プログラマーとして 2 年間、Java を使用する別のチームに切り替えたばかりです。Java ビルダー パターンについて質問があります。

このパターンを使用する利点、つまりテレスコーピング コンストラクターと一貫性のない状態を作成する Java Bean セッターを回避することの利点は理解していますが、それがどのように機能するかを正確に理解するのに苦労しています。チームが使用する必要がある正確なパターンは次のとおりです。

public class Person
{
    //why is it so important that this be final, hence immutable
    private final String firstName;
    private final String lastName;

    // Constructor
    public Person(String firstName, String lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    //I have absolutely no idea what is this for and why is this necessary
    public static Builder builder()
    {
        return new Builder();
    }

    //This is an inner class, where person is the outer class (the owning class)
    //but why is this has to be a static class?
    public static class Builder
    {
        private String firstName;
        private String lastName;

        public Builder withFirstName(String firstName)
        {
            //this.firstName refers to the Builder instance firstName
            this.firstName = firstName;
            return this;
            //what is this return this?  returning this instance of the Builder object?
        }

        public Builder withLastName(String lastName)
        {
            this.lastName = lastName;
            return this;
        }

        public Person build()
        {
            return new Person(firstName, lastName);
            //firstName and lastName here refer to the Builder's object instance vars,
            //and used to create a new person object
        }
    }
}

使用するには:

Person p = new Person.Builder(5).firstName("foo").lastName("bar").build();

1) Builder のパラメータ「5」は何ですか?

2) Builder の内部クラスが静的なのはなぜですか?

3) public static Builder builder() メソッドの使用は何ですか?

4) 実際に新しい内部クラス (Builder オブジェクト) を作成していることは正しいですか? この内部クラス内のビルド メソッドは新しい Person オブジェクトを返しますか?

5) この Person クラスを作成するには、外部クラス用と内部クラス用の 2 倍のメモリ使用量が必要になるようですが、効率が悪いのでしょうか?

6) Person p = new Person("foo", "bar"); によって新しい人物オブジェクトを作成できることは正しいですか?

7) 誰かがこれをどのように単体テストしますか? セッターとゲッターを単体テストする方法は?

8) どのフィールドでもバリデーションを実行できますか?

9) フィールドが必須であることを指定するにはどうすればよいですか。誰かが firstName のみで lastName が指定されていないフィールドを構築しようとすると、例外がスローされます。

よろしくお願いします!

4

1 に答える 1

3
  1. 私はこれを取得しません。クラスにはコンストラクターが定義されていないBuilderため、コンパイラーはパラメーターなしのコンストラクターを自動的に生成します。

  2. クラスが静的でない場合Builder、内側のクラスにアクセスするには、外側のクラスのインスタンスが必要になります。これは「鶏が先か卵が先か」の問題です。内部クラスは外部クラスのインスタンスを取得するために使用されますが、それを使用するにはまず外部クラスのインスタンスが必要です! 修飾子は、外部クラスのstaticインスタンスを使用する必要がないようにします。

  3. これはファクトリ メソッドの例です。今のところ、これは のインスタンスを作成してBuilder返すだけですが、将来的には、インスタンスを作成して返す前に変更するか、インスタンスを返す前にセキュリティ チェックを実行するように変更される可能性があります。

  4. はい、あなたは正しいです。内部クラスのインスタンスを作成し、そのbuildメソッドを使用して外部クラスのインスタンスを取得します。

  5. ほとんどの場合、優れた設計と優れた効率の間にはトレードオフがあります。しかし今回は、メモリ使用量が 2 倍になっていますが (両方のクラスに type の 2 つの変数が含まれているためString)、実際のメモリ使用量はそれほど多くありません。(メモリが不足した場合は、JVM に引数を渡すことで JVM ヒープ領域を変更できます。)

  6. はい、できます。クラスには 2 つのオブジェクトを受け取るpublicコンストラクターがあります。PersonString

  7. Builderのインスタンスを作成し、そのwithFirstNameおよびwithLastNameメソッドを使用して名前を設定し、返されたオブジェクトで getter メソッドを呼び出してPerson、渡された値と等しいかどうかを確認することで、これを単体テストできます (Stringequalsメソッドを使用) )。

  8. クラスのメソッドを使用して、引数が前提条件を満たしているかどうかを確認し、Stringそうでない場合は例外をスローできます。

  9. (デフォルトの初期化が原因で値が渡された場合に発生するという意味だと思います。) Java 7 で導入nullされたクラスで導入された便利なメソッドを利用できます。引数を渡すと、引数が の場合に例外がスローされます。それ以外の場合は、引数を返します。java.util.ObjectsObjects.requireNonNull()null

于 2013-08-24T06:00:52.580 に答える