10

次の手順でクラスを不変にする方法をすでに読んでいる

  1. 「セッター」メソッド(フィールドまたはフィールドによって参照されるオブジェクトを変更するメソッド)を提供しないでください。
  2. すべてのフィールドをファイナルでプライベートにします。
  3. サブクラスがメソッドをオーバーライドすることを許可しないでください。これを行う最も簡単な方法は、クラスをfinalとして宣言することです。より洗練されたアプローチは、コンストラクターをプライベートにし、ファクトリメソッドでインスタンスを構築することです。
  4. インスタンスフィールドに可変オブジェクトへの参照が含まれている場合は、それらのオブジェクトを変更できないようにします
    。可変オブジェクトを変更するメソッドを提供しないでください。
    b。可変オブジェクトへの参照を共有しないでください。コンストラクターに渡された外部の可変オブジェクトへの参照は絶対に保存しないでください。必要に応じて、コピーを作成し、コピーへの参照を保存します。同様に、メソッドで元のオブジェクトが返されないようにするために、必要に応じて内部の可変オブジェクトのコピーを作成します。

不変性のコンテキストでのプライベートコンストラクタとファクトリメソッドの有用性を明確に理解しているのかわかりません。クラスをfinalにすると、基本的に、それを拡張する他のクラスのすべてのパスを閉じます。より洗練されたアプローチはどのように述べられていますか

プライベートコンストラクター、意味のあるシングルトンパターンのファクトリメソッドを見てきました。しかし、オブジェクトの不変性について話すとき、プライベートコンストラクターと静的ファクトリメソッドについて言及するときに、オブジェクトの構築/インスタンス化も制限していますか?

4

8 に答える 8

3

まず、不変クラスが一般的にオーバーライドされるべきではない理由がいくつかあります。ここで見つけることができます。

つまり、コンストラクターをプライベートにすることは、クラスがオーバーライドされるのを防ぐ 1 つの方法にすぎません。なんで?サブクラスでは、すべてのコンストラクターが (暗黙的に)super()基本クラスの既定のコンストラクターである を呼び出すためです。ただし、このコンストラクターをプライベートにすると、サブクラスはそれを呼び出すことができないため、基本クラスをオーバーライドできません。このアプローチは、シングルトンの場合など、特定のクラスのインスタンスの総数を制御する場合に非常に適しています。

于 2012-11-30T17:14:14.457 に答える
2

ここでの大きな問題は、将来のリファクタリングだと思います。後のバージョンで、MyClass のいくつかの新しい特殊なケースをサブクラス MySpecialClass に分割できれば、何かがずっと簡単になることがわかったとします。

MyClass が public コンストラクターを持つ変更可能なクラスである場合、それを実行して、新しい機能のユーザーに新しい MySpecialClass を作成するように指示することができます。既存の使用には影響しません。

MyClass にプライベート コンストラクターとファクトリ メソッドがある場合、問題はありません。また、プライベート コンストラクターを使用して、MyClass にネストされた MySpecialClass を宣言します。ファクトリ メソッドを追加および/または変更して、作成するものを選択しますが、既存の呼び出しが互換性を保って動作することを確認してください。

MyClass が不変で最終的なものであるが、パブリック コンストラクターがある場合はどうしますか?

于 2012-11-30T17:46:20.193 に答える
1

不変性-スレッド環境で可能なさまざまな不変条件の作成を回避するため、並行性に非常に役立ちます。

ファクトリメソッド-読みやすく、カスタム名から理解しやすいため、単なる命名規則です。例:copyOf()メソッドは、コピーコンストラクターを作成するよりも意味があります。効果的なJavaでジョシュアブロックが言ったように

プライベートコンストラクター-シングルトンのようなパターンで独自の用途がありますが、独自の制限があります。

于 2012-11-30T17:36:13.980 に答える
1

うん、君のいうとおりだ。コンストラクターを非公開にしても意味がありません。これにより、インスタンスの作成が制限されますが、これは不変性の望ましいシナリオではありません。

Sun サイトで言及されている例では、コンストラクターを非公開にしません http://docs.oracle.com/javase/tutorial/essential/concurrency/syncrgb.html

于 2012-11-30T17:08:44.793 に答える
1

有効なJavaアイテム15からの私自身の調査結果のいくつか、同じからの関連ステートメントを貼り付けます

「不変性を保証するために、クラスはそれ自体がサブクラス化されることを許可してはならないことを思い出してください。通常、これはクラスを final にすることによって行われますが、別のより柔軟な方法があります。不変クラスを final にする代わりに、すべてのコンストラクターをプライベートまたはパッケージ プライベートにし、パブリック コンストラクターの代わりにパブリック静的ファクトリを追加します (項目 1)。

このアプローチは一般的には使用されませんが、多くの場合、最良の代替手段です。複数のパッケージプライベート実装クラスを使用できるため、最も柔軟です。そのパッケージの外部に存在するクライアントにとって、不変クラスは事実上最終的なものです。これは、別のパッケージから取得され、パブリックまたは保護されたコンストラクターがないクラスを拡張することは不可能であるためです。複数の実装クラスの柔軟性を可能にするだけでなく、このアプローチにより、静的ファクトリのオブジェクト キャッシング機能を改善することで、後続のリリースでクラスのパフォーマンスを調整することが可能になります。

"

次に、静的ファクトリとコンストラクターの利点について説明します

于 2012-11-30T17:50:32.290 に答える
0

これは、プライベート コンストラクターではサブクラスを作成できないため、それを拡張する他のクラスのすべてのパスを制限するためです。シングルトンパターンのように独自の制限/複雑さがあるため、洗練されています。

于 2012-11-30T17:08:55.360 に答える
0

プライベート コンストラクターの背後にある考え方は、同じ内部型の異なるデータを持つ新しいインスタンスの構築を許可しながら、クラス データの不変の実装を隠したいということです。

例えば

public class Temperature
{
    private readonly double temperatureInCelsius;

    public Temperature(string temperatureInCelsius)
    {
         this.temperatureInCelsius = System.Convert.ToDouble(temperatureInCelsius);
    }
    private Temperature(double temperatureInCelsius)
    {
         this.temperatureInCelsius = temperatureInCelsius;
    }

    public Temperature AddCelsius(string temperatureToAddInCelsius)
    {
         return new Temperature(System.Convert.ToDouble(temperatureToAddInCelsius) + temperatureInCelsius);
    }
    public void PrintCelsius(Display display)
    {
        display.Print(temperatureInCelsius);
    }
    public void PrintFarenheit(Display display)
    // ... etc
}

温度を表す文字列からクラスを構築できるという要件がある場合は、例の半ば愚かさを無視します。温度を実際に保存する方法は変更される可能性があり、実装の詳細です。このクラスは、float、string、double、int などを使用するように変更できます。このメソッドは、実装の柔軟性を確保しながら不変性を維持します。コレクション、辞書などのより複雑なオブジェクトをラップする場合、明らかにこれははるかに強力になります。

于 2013-01-31T18:46:59.363 に答える