11

Joshua Blochの「EffectiveJava」(第2版)を読み始めました。項目2(多くのコンストラクターパラメーターに直面したときにビルダーを検討してください)を読んでいる間、作成者がClass.newInstance()メソッドに対して作成する特定のステートメントがあります。具体的には、著者は次のように述べています

Javaでの従来のAbstractFactory実装は、「Class」オブジェクトであり、「newInstance」メソッドが「build」メソッドの一部を果たしています。

この部分は私を少し混乱させました-抽象ファクトリデザインパターンの私の理解は、それがファクトリのファクトリを表すために使用されるということです。私の意見では、 Class.newInstance()メソッドは、「静的ファクトリメソッド」のコーディング哲学(ちなみに、同じ本の項目1)に隣接しています。

考え、誰か?私はいくつかの厳しいインタビューをクラックするために一生懸命準備してきました、そしてそのようなインタビューに現れる前に私のファンダメンタルズがしっかりしていれば本当にありがたいです。

ありがとう。

4

3 に答える 3

6

これが私の意見です。

まず第一に、Abstract Factoryパターンは、ファクトリのファクトリを意図したものではありません。このパターンの重要な側面は、基盤となる(おそらくアクセスできない)ファクトリ実装を備えたアクセス可能なインターフェイスがあり、それを介して(おそらくアクセスできない)オブジェクト実装のアクセス可能なインターフェイスを取得できることです。私が知っているのは、ガンマの本でこのパターンの適用条件のいくつかをどのように理解するかについての長く厄介な言葉遊びです:

  • システムは、その製品がどのように作成され、構成され、表現されるかに依存しない必要があります
  • 製品のクラスライブラリを提供し、実装ではなく、インターフェイスのみを公開したいとします。

最後に、ファクトリではなくオブジェクトを取得します。

第二に、私はパターンの概念と言語のキーワードの間に1:1の関係を作りません。「AbstractFactory」は、必ずしもJavaabstract classまたはinterfaceコンストラクトに変換されるとは限りません。クライアントコードが基盤となるファクトリおよびオブジェクトの実装から独立していることを何らかの方法で保証する限り、「AbstractFactory」を表す通常の拡張可能でインスタンス化可能なクラスを引き続き使用できます。これは、java.lang.Class抽象でもインターフェースでもないの場合ですが、newInstance()メソッドを介して表す型のパラメーターなしのコンストラクター実装を非表示にする役割を果たします。次のように使用すると、おそらくより明確になります。

Object o = Class.forName(type).newInstance();

Class「AbstractFactory」をObject再生し、「AbstractProduct」を型実装に再生します。

最後にnewInstance()、静的ファクトリメソッドではありません。このパターンは、実装されているクラスのインスタンスを返すことを目的としているためだと思います。newInstance()のインスタンスClassもサブも返しませんClass。それが表すタイプのインスタンスを返します。ブロッホが彼の本で述べているように、それはどちらも「ファクトリメソッド」ではありません。

于 2012-09-04T21:48:24.757 に答える
3

AbstractFactoryが「ファクトリのファクトリ」であることを示唆するものは何もないと思います。は、sAbstractFactory<T>を作成するファクトリを作成するのではなく、sを直接作成します。TT

それが抽象的であるという考えは、ロジックを作成Tして注入できるようにすることです。したがって、たとえば、次のようになります。

public interface ConnectionFactory {
    Connection newConnection();
}

//passed to your object normally:
public class RealConnectionFactory implements ConnectionFactory {
    //...
}

//passed to your object when unit testing:
public class FakeConnectionFactory implements ConnectionFactory {
    //...
}

//...

public class MyDao {
   public MyDao(ConnectionFactory connectionFactory) {
       this.conn = connectionFactory.newConnection();
   }
}

この場合、はsConnectionFactoryを作成Connectionしますが、インターフェースであるため抽象的です。

抽象的ではなく、実際には拡張できないため、抽象ファクトリの標準的な例でClass<?>.newInstance()ないことに同意する傾向があります。を要求して、1つの実装で新しい値をに初期化し、別の実装で新しい値をに初期化することはできません。ClassClass<Integer>17

ただし、具体的な実装とを使用したsのClass<? extends InputStream>抽象ファクトリのようなものを言うことで、物事を拡張することができます。ただし、これは「抽象」の従来の意味ではありません(まだ1つのクラスしかありません:) 。InputStreamClass<SocketInputStream>Class<FileInputStream>Class

ただし、「ファクトリ」の新しい具象バージョンを実装する方法は、を拡張する新しいクラスを作成することであるため、それでも抽象ファクトリとしては役に立ちませんInputStream。これは、抽象ファクトリが意図していることではありません。

于 2012-09-04T20:15:37.383 に答える
1

私の意見では、彼は次のようなコードを参照しています。

Integer.class.newInstance();

Class<T>抽象ファクトリはどこにありますか。typeパラメータを渡すと、具体的になりますInteger。次に、「ビルダー」と呼びますnewInstance()

于 2012-09-04T19:47:07.823 に答える