一部のコードでは、次のような静的ファクトリがあります。
public class SomeFactory {
// Static class
private SomeFactory() {...}
public static Foo createFoo() {...}
public static Foo createFooerFoo() {...}
}
コードレビュー中に、これはシングルトンであり、注入されるべきであると提案されました。したがって、次のようになります。
public class SomeFactory {
public SomeFactory() {}
public Foo createFoo() {...}
public Foo createFooerFoo() {...}
}
強調するいくつかのこと:
静的になるために私が持っていた引数は:
シングルトンとしてのファクトリの引数は次のとおりです。
シングルトンアプローチには深刻な問題があります。静的なメソッドは絶対にないようです。 StringUtils
などのユーティリティをラップして挿入する必要があることも示唆しているようですが、これはばかげているようです。最後に、ある時点でファクトリーをモックする必要があることを意味しますが、これは正しくないようです。いつ工場をあざける必要があるか、私には考えられません。
コミュニティはどう思いますか?私はシングルトンアプローチが好きではありませんが、それに対してひどく強い議論をしているようには見えません。
作成するオブジェクトタイプからファクトリを分離するのはなぜですか?
public class Foo {
// Private constructor
private Foo(...) {...}
public static Foo of(...) { return new Foo(...); }
}
これが、Joshua Blochが彼の著書「Effective Java」の5ページにある彼のアイテム1として述べていることです。 Javaは、余分なクラスやシングルトンなどを追加しなくても十分冗長です。別のファクトリクラスが意味をなす場合もありますが、その数は限られています。
Joshua BlochのItem 1を言い換えると、コンストラクターとは異なり、静的ファクトリーメソッドは次のことができます。
短所:
本当に、Blochの本をコードレビュー担当者に渡して、2人がBlochのスタイルに同意できるかどうかを確認する必要があります。
私の頭の真上から、Javaの静的に関する問題のいくつかを次に示します。
静的メソッドは、OOP "ルール"によって再生されません。特定の静的メソッドを実装するように強制することはできません(私が知る限り)。したがって、複数のクラスを持つことはできません。同じシグネチャを使用して同じ静的メソッドのセットを実装します。つまり、何を実行していてもoneで立ち往生しています。静的クラスを実際にサブクラス化することもできません。したがって、ポリモーフィズムはありません、など.
メソッドはオブジェクトではないため、静的メソッドを渡すことはできず、それらを使用することはできません(大量のボイラープレートコーディングを行わないと)exceptそれらにハードリンクされているコードによって- -これにより、クライアントコードが高度に結合されます。 (公平に言うと、これは静力学のせいだけではありません)。
staticsフィールドはグローバルとかなり似ています
あなたは言及しました:
シングルトンアプローチには深刻な問題があります。静的なメソッドは絶対にないようです。また、StringUtilsなどのユーティリティをラップして挿入する必要があることも示唆しているように見えますが、これはばかげているようです。最後に、ある時点でファクトリーをモックする必要があることを意味しますが、これは正しくないようです。いつ工場をあざける必要があるか、私には考えられません。
それは私があなたに尋ねることを好奇心をそそる:
StringUtils
が正しく設計および実装されていると思いますか?あなたが構築しているアプリケーションはかなり単純でなければならないか、そうでなければあなたはそのライフサイクルの比較的初期にいると思います。静的に関する問題が発生していないと考えられる唯一のシナリオは、ファクトリについて知っているコードの他の部分を1つか2つの場所に制限できた場合です。
アプリケーションが進化し、今ではいくつかのインスタンスでFooBar
(Fooのサブクラス)を生成する必要があるとします。次に、SomeFactory
を認識し、someCondition
を参照してSomeFactory
またはSomeOtherFactory
を作成するIFooFactory
を作成したとしましょう。さて、異なるサブクラスまたはまったく異なる実装を作成することは子供の遊びです-チェーンの上位にある適切なIFooFactoryをフィードし、クライアントがそれを取得すると、gimmeAFoo()
を呼び出して正しいものを取得しますそれは正しいファクトリーを得たからです。
これが製品コードでどのように機能するのか疑問に思われるかもしれません。私が取り組んでいるコードベースの1つの例を挙げますと、1年以上のプロジェクトの開始後にレベルが安定し始めています。Questionデータオブジェクトを作成するために使用される一連のファクトリーがあります(これらは次のようなものです- プレゼンテーションモデル )。私はIFoo
を持っています。これは基本的に、どの質問ファクトリをいつ使用するかを調べるためのハッシュです。したがって、さまざまな質問をするアプリケーションを作成するために、さまざまなファクトリをマップに配置しました。
質問は、手順または演習(どちらもQuestionFactoryMap
を実装)で提示できるため、IContentBlock
またはInstructionsFactory
はそれぞれ、QuestionFactoryMapのコピーを取得します。次に、さまざまなInstructionsおよびExerciseファクトリがExerciseFactory
に渡されます。ContentBlockBuilder
は、いつ使用するかのハッシュを保持します。そして、XMLがロードされると、ContentBlockBuilderはハッシュからExerciseまたはInstructions Factoryを呼び出し、それをcreateContent()
に要求します。次に、ファクトリは、質問の作成を、引き出したものに委任します各XMLノードとハッシュの内容に基づいて、その内部QuestionFactoryMapの 残念ながら 、それはBaseQuestion
ではなくIQuestion
ですが、設計に注意を払っていても、間違いを犯す可能性があることを示していますあなたを悩ませることができます。
あなたの腸はこれらの静力学があなたを傷つけるとあなたに言っています、そして確かにあなたの腸をサポートするために文学に そこにたくさん があります。単体テストにのみ使用する依存性注入を使用することで失うことは決してありません(ただし、優れたコードを作成した場合、それ以上使用しないと信じているわけではありません)。コードをすばやく簡単に変更できます。なぜそこに行くのですか?