1

重複の可能性:
コンストラクターの代わりに静的ファクトリー メソッドを提供することを検討してください

これはおそらく物議を醸す質問であり、このフォーラムには適していない可能性があります (したがって、この質問を閉じることを選択しても、私は侮辱されません)。

Javaの現在の機能を考えると、コンストラクターを作成する理由はないようpublicです...これまで. 友好的、、privateprotectedOKですが、public違います。

ほとんどの場合、public staticオブジェクトを作成する方法を提供する方が良い考えのようです。すべての Java Bean シリアライゼーション テクノロジ (JAXB、Jackson、Spring など) は、保護されたまたはプライベートな引数なしのコンストラクタを呼び出すことができます。

私の質問は次のとおりです。

  • この慣習が布告されたり書かれたりしているのを見たことがありませんか?ブロッホが言及しているかもしれませんが、私は本を所有していません。
  • 私が見逃した、おそらくスーパードライではない以外のユースケースはありますか?

編集:静的メソッドが優れている理由を説明します。

.1. 1 つには、より良い型推論が得られます。たとえば、Guava のhttp://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplainedを参照してください。

.2. クラスの設計者は、静的メソッドで返されるものを後で変更できます。

.3. コンストラクターの継承を処理するのは、特に何かを事前に計算する必要がある場合は苦痛です。.4. その他の理由: https://stackoverflow.com/a/3852556/318174

これはパブリック API のようなコード用であることを投稿する必要がありました。私は、ユニット テスト、利便性、および怠け者の原因のために、あらゆる種類の規則 (フィールドへの直接アクセスの使用など) に頻繁に違反します。だから私がこれまでに意味したとき、私はあなたがそれを野生に解放することを意味しました.

4

4 に答える 4

7

以下がメソッドの外観である場合

public class MyClass {

    private MyClass() { }

    public static MyClass getInstance() {
        return new MyClass();
    }
}

次に、パブリックの引数なしコンストラクターを使用することをお勧めします。

そのようなメソッドを呼び出さなければならない場合、オブジェクトを構築するために何かをしているように感じますが、実際にはそうではありません。

コンストラクター自体を呼び出す以外に何もしないメソッドを使用しても意味がないと思います。

于 2012-10-24T16:54:35.303 に答える
5

要するに、静的ファクトリはクールで用途がありますが、一部の API は、付加価値がなく複雑さを追加するだけでも、あらゆる場所でそれらを使用するというわなに陥ります。

Java で静的ファクトリがうまく機能する例の 1 つは、オーバーロードされたコンストラクターとして自然に実装できない名前付きビルダーが多数ある EnumSet です。

たとえば、これらは同じ引数を持っていても同じことをしません。

EnumSet.of(E1, E3);
EnumSet.range(E1, E3);

また、EnumSet は、列挙型の要素数に基づいて 2 つの異なる実装を返します。

    if (universe.length <= 64)
        return new RegularEnumSet<>(elementType, universe);
    else
        return new JumboEnumSet<>(elementType, universe);

残念ながら、EnumMap は同様に機能しないため、実装は 1 つしかありません。


.1. 1 つには、より良い型推論が得られます。たとえば、Guava's を参照してください

したがって、グアバには次のようなメソッドがあります

List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();

Java 7ではこれはちょうど

List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();
Map<KeyType, LongishValueType> map = new LinkedHashMap<>();

これは短いので、新しいメソッドを学ぶ必要はありません.Java 6では、型の二重チェックが必要ない場合は、次のことができます.

List<TypeThatsTooLongForItsOwnGood> list = new ArrayList();
Map<KeyType, LongishValueType> map = new LinkedHashMap();

グアバでは、

Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");

組み込みメソッドはどこにありますか

Set<Type> copySet = new HashSet<String>(elements);
List<String> theseElements = Arrays.asList("alpha", "beta", "gamma");

HashSet からをドロップすると、<String>型の安全性が失われますが、ほとんどの適切な IDE がこのコードをオートコンプリートすることを考えると、実際には入力を節約することはできません。

.2. クラスの設計者は、静的メソッドで返されるものを後で変更できます。

私はYAGNIと言いますが、実装を透過的に大幅に変更することは実際には非常に困難です。コードを再構築または再テストすることなく、完全な下位互換性を備えた代替品をドロップできる可能性はほとんどありません。

.3. コンストラクターの継承を処理するのは、特に何かを事前に計算する必要がある場合は苦痛です。

これは本当ですが、まれです。このような状況では、通常、複雑な構築用のビルダー クラスがあり、factor メソッドだけでは問題を解決できません。


Java ライブラリのほとんどのクラスが静的ファクトリではなくコンストラクタを使用していることを考慮する価値があります。コンストラクターが使用された場所で考えられる唯一のクラスは、後で可能であれば静的ファクトリーを使用するように変更されたのは、自動ボクシング ラッパー クラスでした。どのファクトリ メソッドを呼び出すかを知ることの複雑さは、言語によって隠されています。

Javaの現在の機能を考えると、コンストラクターを公開する理由はないようです...これまで. フレンドリー、プライベート、プロテクトはOKですが、パブリックはダメです。

何かができるからといって、それが良い考えであるとは限りません。

たとえば、すべてのクラス、メソッド、および変数を 1 文字または 2 文字の長さにすることができます (3 文字以上の名前を使用する必要はありません。一部の人々は、これが何らかの形で優れていると信じています)。

ところで、一般的な UNIX コマンドを見れば、多くは 2 文字の長さです。;)

ほとんどの場合、オブジェクトを作成するための public static メソッドを提供することをお勧めします。

シンプルさを好み、コードを不必要に複雑にしない限り。

この慣習が布告されたり書かれたりしているのを見たことがありませんか?

私もそうではありません。おそらく、それは良い考えではないからです。私見では。

私が見逃した、おそらくスーパードライではない以外のユースケースはありますか?

あなたはそれをする正当な理由を述べていませんが、それは私にとってそれをしない十分な理由です. ;)

于 2012-10-24T16:51:29.873 に答える
2

そうは思わない。オブジェクトを作成するにはコンストラクタが必要です。コンストラクターは、null を返す可能性のあるファクトリ メソッドに対して正しくないオブジェクトが実際に作成されたことを保証します。

コンストラクタまたはファクトリ メソッドの選択は、具体的なユース ケースによって異なります。コンストラクターの方が優れている場合もあれば、ファクトリ メソッドの方が優れている場合もあります。

ほとんどの場合、静的ファクトリ メソッドをクラス自体に含めることは悪い習慣だと言いたいです。クラス自体とそのファクトリのIMHO分離は、望ましい解決策です。

すべてのフレームワークがファクトリ メソッドをサポートしているとは思いません。Spring と JAXB は実際にサポートしていますが、たとえば、、HttpServletEJB HttpFilter、アプレットなどには、パブリックのデフォルト コンストラクターが必要です。Spring の場合でも、コンストラクターを持つ Bean の使用は、インスタンス化にファクトリー メソッドを必要とする Bean よりも便利です。

于 2012-10-24T16:54:27.333 に答える
0

パブリック コンストラクターの使用例を 1 つ思いつくことができます。注釈処理フレームワークを使用する場合は、Processor. コンパイラはリフレクションを使用してプロセッサのインスタンスを作成します。システムが機能するためには、実装クラスはジェネリックではなくパブリックであり、引数なしのパブリック コンストラクターを持つ必要があります。

したがって、パブリック コンストラクターは、リフレクションを使用するフレームワークにおそらく役立ちます。

于 2012-10-24T17:28:27.767 に答える