-1

一連の Web サイトで RSS ストリームを取得するために誰かが入力したい次のスケルトン クラスを取り上げます。

public class RSSStream extends Thread {

    public RSSStream(String rssStreamName,String rssURL,int refreshTime){
        // constructor code goes here
    }
}

ここで、refreshTime が 0 より大きくなければならず、rssURL が有効な http アドレスでなければならないことを考えてみましょう。

明白な反射は、コンストラクター内にロジックをチェックするいくつかの値を持つことです。ただし、コンストラクターへの呼び出しは、何が起こってもオブジェクトをインスタンス化します。これは、値がその仕事をすることを許可しない場合、オブジェクトが役に立たなくなることを意味します。これは、オブジェクトを最終的にダンプまたは再利用する必要があることも意味します。

そこで、この件に関するいくつかの質問を以下に示します。

  • 一部のクラスは、おそらくプライベート コンストラクターと組み合わせて getInstance() メソッドを強制するのはなぜですか? よく覚えていれば、1 つの例は GregorianCalendar でしょう。
  • これと同じアプローチをどのような場合に使用しますか?
  • ほとんどの場合、コンストラクターにチェックロジックがありますか?
  • もしそうなら、ドメインモデルの永続コンテキストで使用されるエンティティスタイルのクラスにこれを適用しますか?

すべての回答を歓迎します。最も一般的な方法を明確に理解することは興味深いでしょう。

4

6 に答える 6

3

最も一般的なもののいくつか:

  • 複雑なオブジェクトの構築にFactoryMethodを使用する場合、通常はプライベート コンストラクターがあり、ファクトリによるインスタンス化が必要になります。これにより、工場との建設戦略の切り替えがサポートされます。

  • 私にとって最も明確なのは、インスタンス化が発生しない場合、コンストラクターでカスタム (そしてできれば有益な) 例外をスローすることです: :

    パブリック クラス Person {

        public Person(Integer id, String name) throws InvalidPersonException
             if (name==null) throw new InvalidPersonException("You cant have a person without a name");
             ...
    
  • これにより、エンティティ永続オブジェクトが混乱する可能性があります。これは主に、これらのオブジェクトをロジックから解放したいためであり、フレームワークがこれを処理する必要があるためです。たとえば、休止状態で (id, name) を含む Bean がある場合はnull 以外の名前が必要なテーブルに永続化するには、データベースがスローするエラーまたは構成からのエラーで十分です。

于 2009-12-06T19:26:44.220 に答える
2

実行する必要のある値チェックによってオブジェクトインスタンスが破損した状態になる可能性がある場合は、インスタンスを生成するためのファクトリの作成を検討する必要があります。これにより、渡された引数が無効な場合に例外をスローできます。

ただし、検証が失敗した場合にオブジェクトをコンストラクターでデフォルト値で「修正」できる場合は、デフォルト値を使用して、役に立たないが破損していないオブジェクトを呼び出し元に提供します。

于 2009-12-06T19:26:25.483 に答える
2

引数を検証する必要があるコンストラクターは、通常、検証が失敗した場合に をスローしIllegalArgumentExceptionます。コンストラクターが例外をスローすると、「途中で初期化された」オブジェクトが心配する必要はありません。

于 2009-12-06T19:50:28.650 に答える
2

コンストラクターが例外をスローした場合、オブジェクトへの参照は返されないため、オブジェクトはすぐにガベージ コレクションされます。したがって、メモリを無駄にしません。オブジェクト、特に不変オブジェクトを構築するときはいつでも、これが検証を行うのに適した場所だと思います。

getInstance() は、サブクラスのインスタンスを返すファクトリ メソッドです。状況に応じて異なるサブクラスを返す場合に使用します。たとえば、Calendar.getInstance() は自分のロケールでは GregorianCalendar を返しますが、ロケール設定が異なる場合は別の実装を返す可能性があります。

オブジェクトを作成するためのさまざまなパターンについては、http://en.wikipedia.org/wiki/Creational_patternを確認してください。

お役に立てれば

于 2009-12-06T19:30:57.247 に答える
2
  • 私は主getInstance()に、Singleton パターンを使用するためだけに、静的でプライベートなコンストラクターを見て使用しました。ただし、Java のCalendar抽象クラスは、このメソッドをシングルトンではなく、デフォルトのタイムゾーンとロケールでデフォルトの実装 (グレゴリオ暦) をインスタンス化するために使用します。おそらく、これCalendarは抽象的でインスタンス化できないために行われます。 GregorianCalendar実際にはパブリックコンストラクターがあります。
  • ほとんどの場合、引数のないパブリック コンストラクターとセッター メソッドを使用し、チェック ロジックと例外スローをセッター メソッドに配置します。私は Spring の依存性注入を頻繁に使用します。必要なすべての属性が設定されていない場合、@Requiredアノテーションを使用してコンテナーに例外をスローさせることができます。
  • この種のロジックをエンティティ オブジェクトに適用することはありません。単純にするためにすべてのロジックをエンティティ オブジェクトから除外し、厳密に POJO にするようにしています。
于 2009-12-06T19:32:31.743 に答える
2

この特定のケースでは、コンストラクターで引数の検証を行い、説明的なエラー メッセージと共に IllegalArgumentException をスローします。オブジェクトは作成されず、呼び出し元のコードを修正する必要があります。

これは getInstance() メソッドでも実行できます。getInstance() を使用する理由の 1 つは、インスタンスが非常に共有可能であり、作成するオブジェクトの数を削減する場合です。たとえば、同じ URL を持つ複数の RSSStream オブジェクトを持つことができる場合、getInstance() を設定してそれらのインスタンスを共有できます。(これは、インスタンスが不変であることを前提としています。)

Builder パターンもあります。RSSStream.Builder というネストされた内部クラスがあり、次のように言います。

RSSStream rss = new RSSStream.Builder.build(url)
                                     .name("stack overflow")
                                     .refreshTime(2)
                                     .build();

このパターンにより、クライアント コードがより自己記述的になり、RSSStream が無効な状態でビルドされることがなくなります (ビルダーのメソッドが IllegalArgumentException をスローします)。ビルダーは、すべてのパブリック コンストラクターを置き換えるのに十分な柔軟性を備えています。

私は通常、IllegalArgumentException をコンストラクターからスローするか、検証メソッド (複数のコンストラクターからエラー チェック コードを除外するため) を使用しました。より重要なパブリック API に Builder メソッドを使い始めて、とても気に入っています。

これらの手法は、ドメイン モデル クラスで確実に使用できます。

于 2009-12-06T19:36:36.847 に答える