web-dev-qa-db-ja.com

静的ファクトリーメソッドとは

「静的ファクトリ」メソッドとは何ですか?

233
freddiefujiwara

データベース接続はリソースを大量に消費するため、データベース接続への直接アクセスは提供しません。そのため、制限を下回っている場合に接続を作成する静的なファクトリメソッドgetDbConnectionを使用します。それ以外の場合、「スペア」接続を提供しようとし、接続がない場合は例外で失敗します。

public class DbConnection{
   private static final int MAX_CONNS = 100;
   private static int totalConnections = 0;

   private static Set<DbConnection> availableConnections = new HashSet<DbConnection>();

   private DbConnection(){
     // ...
     totalConnections++;
   }

   public static DbConnection getDbConnection(){

     if(totalConnections < MAX_CONNS){
       return new DbConnection();

     }else if(availableConnections.size() > 0){
         DbConnection dbc = availableConnections.iterator().next();
         availableConnections.remove(dbc);
         return dbc;

     }else {
         throw new NoDbConnections();
     }
   }

   public static void returnDbConnection(DbConnection dbc){
     availableConnections.add(dbc);
     //...
   }
}
112

static factory method pattern は、オブジェクト作成をカプセル化する方法です。ファクトリメソッドがなければ、クラスの constructor を直接呼び出します:Foo x = new Foo()。このパターンでは、代わりにファクトリメソッドFoo x = Foo.create()を呼び出します。コンストラクターはprivateとしてマークされているため、クラス内から以外は呼び出すことができません。また、ファクトリメソッドは static としてマークされているため、最初にオブジェクトがなくても呼び出すことができます。

このパターンにはいくつかの利点があります。 1つは、ファクトリが多くのサブクラス(またはインターフェイスの実装者)から選択して返すことができることです。このようにして、呼び出し側は、潜在的に複雑なクラス階層を知ったり理解したりする必要なく、パラメーターを介して必要な動作を指定できます。

別の利点は、マシューとジェームズが指摘したように、接続などの限られたリソースへのアクセスを制御することです。これを実装する方法 再利用可能なオブジェクトのプール -オブジェクトを構築、使用、および破棄する代わりに、構築と破壊が高価なプロセスである場合、一度構築してリサイクルする方が理にかなっている場合があります。ファクトリメソッドは、既存の未使用のインスタンス化されたオブジェクトがある場合はそれを返すか、オブジェクト数が下限しきい値を下回る場合は構築し、上限しきい値を超える場合は例外をスローするか、nullを返します。

ウィキペディアの記事にあるように、複数のファクトリメソッドにより、類似した引数タイプの異なる解釈も可能になります。通常、コンストラクターはクラスと同じ名前を持ちます。つまり、指定された signature を持つコンストラクターは1つしか持てません。ファクトリーはそれほど制約されていません。つまり、同じ引数タイプを受け入れる2つの異なるメソッドを使用できます。

Coordinate c = Coordinate.createFromCartesian(double x, double y)

そして

Coordinate c = Coordinate.createFromPolar(double distance, double angle)

Rasmusが指摘しているように、これは読みやすさを改善するためにも使用できます。

445
Jason Owen

注意! 「静的ファクトリーメソッドNOTファクトリーメソッドパターンと同じです」(c)有効なJava、Joshua Bloch。

Factoryメソッド:「オブジェクトを作成するためのインターフェイスを定義しますが、インターフェイスを実装するクラスにインスタンス化するクラスを決定させます。Factoryメソッドにより、クラスはインスタンス化をサブクラスに延期できます」(c)GoF。

「静的ファクトリメソッドは、クラスのインスタンスを返す静的メソッドです。」 (c)効果的なJava、Joshua Bloch。通常、このメソッドは特定のクラス内にあります。

違い:

静的ファクトリメソッドの重要な考え方は、オブジェクトの作成を制御し、コンストラクタから静的メソッドに委任することです。作成されるオブジェクトの決定は、メソッドの外部で行われた抽象ファクトリーのようなものです(一般的なケースですが、常にではありません)。 Factory Methodの重要な(!)アイデアは、Factoryメソッド内に作成するクラスのインスタンスの決定を委任することです。例えば。クラシックシングルトン実装は、静的ファクトリメソッドの特殊なケースです。一般的に使用される静的ファクトリメソッドの例:

  • valueOf
  • getInstance
  • newInstance
153

静的ファクトリーメソッドによって読みやすさを改善できます。

比較する

public class Foo{
  public Foo(boolean withBar){
    //...
  }
}

//...

// What exactly does this mean?
Foo foo = new Foo(true);
// You have to lookup the documentation to be sure.
// Even if you remember that the boolean has something to do with a Bar
// you might not remember whether it specified withBar or withoutBar.

public class Foo{
  public static Foo createWithBar(){
    //...
  }

  public static Foo createWithoutBar(){
    //...
  }
}

// ...

// This is much easier to read!
Foo foo = Foo.createWithBar();
67
Rasmus Faber
  • コンストラクタとは異なり、コードを明確にする名前があります。
  • 呼び出しごとに新しいオブジェクトを作成する必要はありません-必要に応じて、オブジェクトをキャッシュして再利用できます。
  • 戻り値の型のサブタイプを返すことができます-特に、呼び出し元が実装クラスを知らないオブジェクトを返すことができます。これは、静的ファクトリメソッドの戻り値型としてインターフェイスを使用する多くのフレームワークで非常に価値があり、広く使用されている機能です。

from http://www.javapractices.com/topic/TopicAction.do?Id=21

20
soldier.moth

それはすべて、保守性に要約されます。これを配置する最善の方法は、newキーワードを使用してオブジェクトを作成するときは常に、作成しているコードを実装に結合することです。

ファクトリパターンを使用すると、オブジェクトの作成方法とオブジェクトの操作方法を分離できます。コンストラクターを使用してすべてのオブジェクトを作成する場合、その実装にオブジェクトを使用するコードを本質的にハードワイヤリングします。オブジェクトを使用するコードは、そのオブジェクトに「依存」しています。これは表面的には大したことではないように思えるかもしれませんが、オブジェクトが変更されたとき(コンストラクターの署名を変更したり、オブジェクトをサブクラス化することを考えてください)、どこにでも戻って物事を再配線する必要があります。

今日、工場は、それ自体を維持するのが少し難しいことが判明した多くのボイラープレートコードを必要とするため、依存性注入を使用することを支持して大部分が刷新されました。依存性注入は基本的にファクトリと同等ですが、オブジェクトを宣言的に(構成または注釈を介して)ワイヤリングする方法を指定できます。

18
cwash

クラスのコンストラクターがプライベートの場合、外部からクラスのオブジェクトを作成することはできません。

class Test{
 int x, y;
 private Test(){
  .......
  .......
  }
}

上記のクラスのオブジェクトを外部から作成することはできません。したがって、クラスの外部からx、yにアクセスすることはできません。次に、このクラスの用途は何ですか?
回答は次のとおりです。 工場 方法。
上記のクラスに以下のメソッドを追加します

public static Test getObject(){
  return new Test();
}

そのため、このクラスのオブジェクトを外部から作成できます。方法のように...

Test t = Test.getObject();

したがって、プライベートコンストラクターを実行してクラスのオブジェクトを返す静的メソッドは、 工場 方法

10
Santhosh

私が知っていることについて、この投稿にいくつかの光を加えると思いました。 recent Android projectでこの手法を広範囲に使用しました。 creating objects using new operatorの代わりに、static methodを使用してクラスをインスタンス化することもできます。コードリスト:

//instantiating a class using constructor
Vinoth vin = new Vinoth(); 

//instantiating the class using static method
Class Vinoth{
  private Vinoth(){
  }
  // factory method to instantiate the class
  public static Vinoth getInstance(){
    if(someCondition)
        return new Vinoth();
  }
}

静的メソッドは条件付きオブジェクト作成をサポートしています:コンストラクターを呼び出すたびにオブジェクトが作成されますが、それは望ましくない場合があります。何らかの条件を確認してから新しいオブジェクトを作成したい場合、条件が満たされない限り、毎回Vinothの新しいインスタンスを作成するわけではありません。

Effective Javaから取得した別の例。

public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
}

このメソッドは、ブール値のプリミティブ値をブール値のオブジェクト参照に変換します。 Boolean.valueOf(boolean)メソッドは、オブジェクトを作成しないことを示しています。繰り返されるinvocationsから同じオブジェクトを返すstatic factory methodsの機能により、クラスはいつでも存在するインスタンスを厳密に制御できます。

Static factory methodsは、constructorsとは異なり、戻り型のobjectsubtypeを返すことができるということです。この柔軟性の1つの用途は、APIがクラスを公開せずにオブジェクトを返すことができることです。この方法で実装クラスを非表示にすると、APIが非常にコンパクトになります。

Calendar.getInstance()は上記の優れた例です。ロケールに応じてBuddhistCalendarJapaneseImperialCalendar、またはデフォルトで1つのGeorgianを作成します。

私が考えることができる別の例はSingleton patternであり、コンストラクターをプライベートにして独自のgetInstanceメソッドを作成し、常に1つのインスタンスしか使用できないようにします。

public class Singleton{
    //initailzed during class loading
    private static final Singleton INSTANCE = new Singleton();

    //to prevent creating another instance of Singleton
    private Singleton(){}

    public static Singleton getSingleton(){
        return INSTANCE;
    }
}
8
Thalaivar

ファクトリメソッド。オブジェクトのインスタンス化を抽象化するメソッド。一般に、ファクトリは、何らかのインターフェイスを実装するクラスの新しいインスタンスが必要であることを知っているが、実装クラスがわからない場合に役立ちます。

これは、関連するクラスの階層を操作するときに役立ちます。この良い例は、GUIツールキットです。各ウィジェットの具体的な実装のために、コンストラクターへの呼び出しを単純にハードコードすることもできますが、あるツールキットを別のツールキットに交換したい場合は、変更する場所がたくさんあります。ファクトリを使用すると、変更する必要があるコードの量を減らすことができます。

4
Bryan Kyle

Staticファクトリーに由来する利点の1つは、APIがクラスを公開せずにオブジェクトを返すことができることです。これは非常にコンパクトなAPIにつながります。 Javaでは、これは約32クラスを非表示にするCollectionsクラスによって達成され、コレクションAPIを非常にコンパクトにします。

3
Rakesh Chauhan

静的

キーワード 'static'で宣言されたメンバー。

工場メソッド

新しいオブジェクトを作成して返すメソッド。

javaで

プログラミング言語は「静的」の意味に関連していますが、「工場」の定義には関連していません。

1
user207421

静的ファクトリメソッドは、1つのインスタンスのみが使用する具象クラスを返すようにする場合に適しています。

たとえば、データベース接続クラスでは、データベース接続を作成するクラスを1つだけにすることができます。これにより、MysqlからOracleに切り替える場合は、1つのクラスのロジックを変更するだけで、残りのアプリケーションは新しい接続を使用します。

データベースプーリングを実装する場合は、アプリケーションの他の部分に影響を与えることなくそれも実行されます。

これは、目的である工場に対して行う変更からアプリケーションの残りの部分を保護します。

静的である理由は、限られたリソース(ソケット接続またはファイルハンドルの数)を追跡したい場合、このクラスが渡された数と返された数を追跡できるためです。限られたリソース。

1
James Black

Java実装には、ユーティリティクラスJava.util.ArraysおよびJava.util.Collectionsそれらの両方には、静的ファクトリメソッド、その例、および使用方法が含まれています:

また、Java.lang.Stringクラスには、そのようなstatic factoryメソッドがあります

  • String.format(...), String.valueOf(..), String.copyValueOf(...)

プライベートコンストラクターを使用した静的ファクトリメソッドの利点の1つ(インスタンスが外部で作成されないようにするために、外部クラスのオブジェクト作成を制限する必要があります)は、instance-controlledクラス。また、インスタンス制御クラスは、プログラムの実行中に2つの等しい別個のインスタンスが存在しないことを保証します(a.equals(b)if and only if a == b==演算子の代わりに等しいメソッド(Effective Javaによる)。

繰り返しの呼び出しから同じオブジェクトを返す静的ファクトリメソッドの機能により、クラスはいつでもどのインスタンスが存在するかを厳密に制御できます。これを行うクラスは、インスタンス制御されていると言われています。インスタンス制御のクラスを作成する理由はいくつかあります。インスタンス制御により、クラスはシングルトン(項目3)またはインスタンス化不可能(項目4)であることを保証できます。また、不変クラス(項目15)が2つの等しいインスタンスが存在しないことを保証することを許可します。a== bの場合にのみa.equals(b)。クラスがこの保証を行う場合、クライアントはequals(Object)メソッドの代わりに==演算子を使用できます。これにより、パフォーマンスが向上する可能性があります。列挙型(アイテム30)は、この保証を提供します。

Effective Javaから、Joshua Bloch(項目1、6ページ)

0