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