「静的ファクトリ」メソッドとは何ですか?
14 に答える
静的ファクトリ メソッド パターンは、オブジェクトの作成をカプセル化する方法です。ファクトリ メソッドがなければ、クラスのコンストラクタを直接呼び出すだけですFoo x = new Foo()
。このパターンでは、代わりにファクトリ メソッドを呼び出します Foo x = Foo.create()
。コンストラクターはプライベートとマークされているため、クラス内以外から呼び出すことはできず、ファクトリ メソッドはstatic
最初にオブジェクトを持たずに呼び出すことができるようにマークされています。
このパターンにはいくつかの利点があります。1 つは、ファクトリが多くのサブクラス (またはインターフェイスの実装者) から選択して返すことができることです。このようにして、呼び出し元は、潜在的に複雑なクラス階層を知ったり理解したりすることなく、パラメーターを介して必要な動作を指定できます。
もう 1 つの利点は、Matthew と James が指摘したように、接続などの限られたリソースへのアクセスを制御できることです。これは、再利用可能なオブジェクトのプールを実装する方法です。オブジェクトを構築、使用、破棄する代わりに、構築と破棄が高価なプロセスである場合は、それらを一度構築してリサイクルする方が理にかなっています。ファクトリ メソッドは、既存の未使用のインスタンス化されたオブジェクトがある場合はそれを返すか、オブジェクト数が下限しきい値を下回っている場合はオブジェクトを構築するかnull
、上限しきい値を上回っている場合は例外をスローするか戻ることができます。
ウィキペディアの記事によると、複数のファクトリ メソッドでは、同様の引数タイプの異なる解釈も可能です。通常、コンストラクターはクラスと同じ名前を持ちます。これは、特定の署名を持つコンストラクターを 1 つだけ持つことができることを意味します。ファクトリはそれほど制約されていません。つまり、同じ引数の型を受け入れる 2 つの異なるメソッドを使用できます。
Coordinate c = Coordinate.createFromCartesian(double x, double y)
と
Coordinate c = Coordinate.createFromPolar(double distance, double angle)
Rasmus氏が指摘しているように、これは可読性を向上させるためにも使用できます。
ノート!「静的ファクトリ メソッドは、ファクトリ メソッドパターンと同じではありません」 (c) 効果的な Java、Joshua Bloch。
Factory メソッド: 「オブジェクトを作成するためのインターフェイスを定義しますが、インスタンス化するクラスをインターフェイスを実装するクラスに決定させます。Factory メソッドにより、クラスはインスタンス化をサブクラスに任せることができます」(c) GoF.
「静的ファクトリ メソッドは、クラスのインスタンスを返す単純な静的メソッドです。」(c) 実効ジャワ、ジョシュア・ブロッホ。通常、このメソッドは特定のクラス内にあります。
違い:
静的ファクトリ メソッドの重要なアイデアは、オブジェクトの作成を制御し、それをコンストラクターから静的メソッドに委譲することです。作成するオブジェクトの決定は、メソッドの外部で行われる Abstract Factory のようなものです (一般的なケースですが、常にではありません)。Factory Method の重要な (!) アイデアは、Factory Method 内で作成するクラスのインスタンスの決定を委譲することです。たとえば、従来の Singleton 実装は、静的ファクトリ メソッドの特殊なケースです。一般的に使用される静的ファクトリ メソッドの例:
- 値の
- getInstance
- 新しいインスタンス
データベース接続はリソースを大量に消費するため、データベース接続への直接アクセスを提供することは避けています。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);
//...
}
}
可読性は、静的ファクトリ メソッドによって改善できます。
比較
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();
- コードを明確にすることができるコンストラクターとは異なり、名前があります。
- 呼び出しのたびに新しいオブジェクトを作成する必要はありません。必要に応じて、オブジェクトをキャッシュして再利用できます。
- 戻り型のサブタイプを返すことができます。特に、呼び出し元に実装クラスが不明なオブジェクトを返すことができます。これは、静的ファクトリメソッドのリターンタイプとしてインターフェイスを使用する多くのフレームワークで非常に価値があり、広く使用されている機能です。
それはすべて保守性に要約されます。これを表現する最良の方法は、new
キーワードを使用してオブジェクトを作成するときはいつでも、作成しているコードを実装に結合していることです。
ファクトリ パターンを使用すると、オブジェクトの作成方法とオブジェクトの操作を分離できます。コンストラクターを使用してすべてのオブジェクトを作成すると、基本的に、オブジェクトを使用するコードをその実装に配線することになります。オブジェクトを使用するコードは、そのオブジェクトに「依存」しています。これは表面上は大したことではないように思えるかもしれませんが、オブジェクトが変更された場合 (コンストラクターのシグネチャの変更やオブジェクトのサブクラス化を考えてみてください)、元に戻ってあらゆる場所で配線をやり直す必要があります。
今日のファクトリは、依存性注入を使用することを支持して大部分が脇に追いやられています。これは、それ自体を維持するのが少し難しいことが判明した多くのボイラープレート コードを必要とするためです。依存性注入は基本的にファクトリと同等ですが、オブジェクトを宣言的に (構成または注釈を介して) 結び付ける方法を指定できます。
クラスのコンストラクターがプライベートの場合、クラスの外部からクラスのオブジェクトを作成することはできません。
class Test{
int x, y;
private Test(){
.......
.......
}
}
上記のクラスのオブジェクトを外部から作成することはできません。したがって、クラス外から x, y にアクセスすることはできません。では、このクラスの用途は何ですか?
これが答えです:FACTORYメソッド。
上記のクラスに以下のメソッドを追加します
public static Test getObject(){
return new Test();
}
これで、このクラスのオブジェクトを外部から作成できます。通りのように...
Test t = Test.getObject();
したがって、プライベートコンストラクターを実行してクラスのオブジェクトを返す静的メソッドは、FACTORYメソッドと呼ばれ
ます。
私が知っていることについて、この投稿にいくつかの光を追加すると思いました。この手法は、 で広く使用されています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 の新しいインスタンスを作成することはありません。
効果的な Javaから取られた別の例。
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
このメソッドは、ブール プリミティブ値をブール オブジェクト参照に変換します。このBoolean.valueOf(boolean)
メソッドは私たちを示していますが、オブジェクトを作成することはありません。static factory methods
繰り返しから同じオブジェクトを返す機能invocations
により、クラスは常にどのインスタンスが存在するかを厳密に制御できます。
Static factory methods
とは異なり、戻り値の型のいずれかをconstructors
返すことができるということです。この柔軟性の応用の 1 つは、クラスを公開せずに API がオブジェクトを返すことができることです。このように実装クラスを非表示にすると、非常にコンパクトな API になります。object
subtype
Calendar.getInstance() は上記の優れた例です。ロケールに応じて a BuddhistCalendar
、JapaneseImperialCalendar
またはデフォルトで oneを作成します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;
}
}
ファクトリメソッドオブジェクトのインスタンス化を抽象化するメソッド。一般に、ファクトリは、何らかのインターフェイスを実装するクラスの新しいインスタンスが必要であることがわかっているが、実装するクラスがわからない場合に役立ちます。
これは、関連するクラスの階層を操作するときに役立ちます。この良い例は、GUIツールキットです。各ウィジェットの具体的な実装のためにコンストラクターへの呼び出しをハードコーディングすることもできますが、あるツールキットを別のツールキットに交換したい場合は、変更する場所がたくさんあります。ファクトリを使用することで、変更する必要のあるコードの量を減らすことができます。
静的ファクトリから生じる利点の 1 つは、その API がクラスを公開せずにオブジェクトを返すことができることです。これにより、API が非常にコンパクトになります。Java では、これはコレクション API を非常にコンパクトにする約 32 個のクラスを隠す Collections クラスによって実現されます。
プライベート コンストラクターを使用した静的ファクトリ メソッドの利点の 1 つは (インスタンスが外部で作成されないようにするために、オブジェクトの作成は外部クラスに対して制限されている必要があります)、インスタンス制御のクラスを作成できることです。また、インスタンス制御クラスは、プログラムの実行中に 2 つの等しい個別のインスタンスが存在しないことを保証します ( a.equals(b) 場合は a==b の場合のみ) 。これは、 equalsメソッドの代わりに==演算子を使用してオブジェクトの等価性をチェックできることを意味します。、効果的なJavaによると。
繰り返し呼び出しから同じオブジェクトを返す静的ファクトリ メソッドの機能により、クラスは常にどのインスタンスが存在するかを厳密に制御できます。これを行うクラスは、インスタンス制御であると言われます。インスタンス制御クラスを作成する理由はいくつかあります。インスタンス制御により、クラスはそれがシングルトン (項目 3) またはインスタンス化不可能 (項目 4) であることを保証できます。また、不変クラス (項目 15) が、2 つの等しいインスタンスが存在しないことを保証できるようにします: a.equals(b) は、a==b の場合のみです。クラスがこの保証を行う場合、そのクライアントは equals(Object) メソッドの代わりに == 演算子を使用できるため、パフォーマンスが向上する可能性があります。列挙型 (項目 30) は、この保証を提供します。
効果的なJava、Joshua Bloch(アイテム1、6ページ)から
Java 実装にはユーティリティ クラスjava.util.Arraysとjava.util.Collectionsが含まれており、どちらにも静的ファクトリ メソッド、その例、および使用方法が含まれています。
Arrays.asList("1","2","3")
Collections.synchronizedList(..), Collections.emptyList(), Collections.unmodifiableList(...)
(いくつかの例のみ、mor メソッドの例について javadocs を確認できます https://docs.oracle.com/javase/8/docs/api/java/util/Collections.html )
また、java.lang.Stringクラスには、次のような静的ファクトリ メソッドがあります。
String.format(...), String.valueOf(..), String.copyValueOf(...)
静的ファクトリ メソッドは、使用する具象クラスを 1 つのインスタンスだけが返すようにしたい場合に適しています。
たとえば、データベース接続クラスでは、データベース接続を作成するクラスを 1 つだけ持つことができます。これにより、Mysql から Oracle に切り替えることにした場合、1 つのクラスのロジックを変更するだけで、アプリケーションの残りの部分は自動的に変更されます。新しい接続を使用します。
データベース プーリングを実装する場合は、アプリケーションの残りの部分に影響を与えることなく実行できます。
ファクトリに加えられる可能性のある変更からアプリケーションの残りの部分を保護します。これが目的です。
静的である理由は、限られたリソース (ソケット接続またはファイル ハンドルの数) を追跡したい場合、このクラスは渡されて返された数を追跡できるため、限られた資源。
静的
キーワード「static」で宣言されたメンバー。
ファクトリーメソッド
新しいオブジェクトを作成して返すメソッド。
Javaで
プログラミング言語は「静的」の意味には関係がありますが、「工場」の定義には関係ありません。