JAVA静的工場方法


静的ファクトリ法は、クラスのコンストラクタを補完または置換するためにクラスがクラスインスタンスを生成する静的方法である.たとえばBooleanには、valueOfが静的ファクトリメソッドであるコードセグメントがあります.
//...
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
//... 
public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
}

注意、ファクトリモードにはファクトリメソッドもありますが、これはここの静的ファクトリメソッドとは異なります.静的ファクトリメソッドを使用してクラスを提供する例には、次の利点があります.1)スタティックファクトリメソッドはクラス名と異なる名前を持つことができ、ユーザは方法名からその用途を推測しやすく、例えばBigIntegerクラスにスタティックファクトリメソッドがある
public static BigInteger probablePrime(int bitLength, Random rnd){
    //...
}

この方法は、ユーザに質量数の可能性が高い大きな整数を返す.2)上記BooleanクラスのメソッドvalueOfによって表されるように、静的ファクトリメソッドは、クラスのインスタンスを新たに生成する必要はなく、クラスのインスタンスを返すだけであり、効率的な改善を提供することがしばしば可能である.静的ファクトリメソッドは、クラスが一度だけインスタンス化されることを保証するために、単一のインスタンスモード(Effective Javaでは列挙タイプを使用して単一のインスタンスを実装することを推奨する)によく使用されます.他の場所では、クラスのインスタンスが常に同じインスタンスを返す必要があります.
public class Singleton {
    //     ,JVM            ,        ,        
    private static final Singleton INSTANCE = new Singleton(); 
    private Singleton() {
        //do something here
    }
    public static Singleton getInstance(){
        return INSTANCE;
    }
}

また,可変クラス(immutable class)を実現する際にも,クラスのインスタンスを静的ファクトリ法で提供することが多い.3)スタティックファクトリメソッドは,現在のクラスのサブクラスインスタンスを返すことができ,サブクラスを露出させない前提でサブクラスのインスタンスを使用することができ,これも構造メソッドに備わっていない機能である.
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E> implements Cloneable, java.io.Serializable
{
    //...
    public > EnumSet noneOf(Class<E> elementType){
        Enum>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }
}

抽象クラスEnumSetの静的ファクトリメソッドで、列挙タイプのサイズに基づいて、異なるEnumSetのサブクラスインスタンスを返します.このようなもう一つの利点は,解結合であり,さらに機能の拡張が容易であることである.たとえば,将来効率のよいEnumSetのサブクラスがある場合,条件に従って新しいサブクラスインスタンスを返すだけでよいが,このメソッドを用いたコードは修正されない.
JDBCはサービスプロバイダのフレームワークとして,静的ファクトリ法も用いた.Service Providerフレームワークには、3つの必須コンポーネントがあります.
  • Service interfaceは、クライアント呼び出しのためにサービスを抽象的に統一して宣言します.
  • は、各サービスプロバイダによって具体的に実装.
  • Provider registration APIは、サービスインターフェースが実装されたProviderを登録するために使用され、クライアントが実装されたサービス
  • にアクセスできるようにする.
  • Service access APIは、通常、ユーザがProviderのインスタンスを取得して具体的な使用を行うことができる静的ファクトリメソッドを介して使用される.

  • JDBCフレームワークの結合
  • java.sql.Connectionはサービスインターフェース(Service interface)であり、prepareStatement(),commit()rollback()などの一連の標準的なサービス内容を定義しているが、これらのサービスは実現されていない.サービスプロバイダProvider(Mysql、Oracleなど)は、これらのサービス内容を独自の特徴に基づいて実現することができます.これらのサービス内容は、Provider対応の実装クラス(例えばoracle.jdbc.driver.PhysicalConnectionクラスですが、この特定の実装クラスが何であるかは気にしません)implementsがJDBCの標準インタフェースjava.sql.Connectionを使用して可用性を保証することができます.
  • java.sql.DriverManager.getConnection()はサービスアクセスAPIの静的ファクトリメソッドであり、パラメータに基づいて対応するConnectionを返し、パラメータは返す必要があるConnectionの実装クラスを示す.
  • java.sql.DriverはService provider interfaceに対応し、Providerはこのインタフェースの実装クラスを提供した後、実装クラスに静的コードがあり、java.sql.DriverManager.registerDriver()メソッドを呼び出してユーザーが使用するためにシステムに登録する.
  • static {  
        try {
            if(defaultDriver == null){
                defaultDriver = new OracleDriver();
                java.sql.DriverManager.registerDriver(defaultDriver);
            }
        } catch (RuntimeException localRuntimeException) {
        } catch (SQLException localSQLException) {  
        }
    }  

    この静的コードは、データベース接続を確立する前に、データベース接続を明示的に呼び出すためにClass.forName(“oracle.jdbc.driver.OracleDriver”);を呼び出してDriverクラスをロードするためにJVMがクラスをロードするときに自動的に実行されます.
    以上の説明から分かるように、静的ファクトリメソッドの役割は主に1つの自己またはサブクラスのインスタンスを生成し、それによって自身の機能と記述を改善することである.ファクトリモードは、クライアントが製品クラスのインスタンスを使用する必要がある場合、newまたは製品クラスの静的ファクトリメソッドによってインスタンスを生成する必要はなく、まずファクトリクラスを作成するために、次に、工場クラスが提供する方法によって製品クラスの例を得る.工場モデルに関する研究は、次の博文で詳細に紹介する.