抽象ファクトリメソッドモード


サンプルコード


この例では、AnimalFactoryとColorFactoryの2つの工場を実施します.次にAbstraactFactoryを使用してアクセス権を管理します.

まずAnimalインタフェースを作成します.
public interface Animal {
    String getAnimal();
    String makeSound();
}
次に、Animalインタフェースの実装チェーンDuckクラスを作成します.
public class Duck implements Animal {
	
    @Override
    public String getAnimal() {
    	return "Duck";
    }
    
    @Override
    public String makeSound() {
    	return "Squeks";
    }
}
これにより、「動物インタフェース」(Dog、Bearなど)をより具体的に実装することができます.
抽象的なファクトリインタフェースを作成できる複数のシリーズが用意されています.
public interface AbstractFactory<T> {
    T create(String animalType);
}
次に、ファクトリメソッドアレイを使用してAnimalFactoryを作成します.
public class AnimalFactory implements AbstractFactory<Animal> {
    
    @Override
    public Animal create(String animalType) {
        if ("Dog".equalsIgnoreCase(animalType)) {
            return new Dog();
        } else if ("Duck".equalsIgnoreCase(animalType)) {
            return new Duck();
        }
        return null;
    }
}
これらのすべての設定が完了すると、GetFactory()が提供するパラメータに基づいて、AnimalFactoryを提供するFactory Providerクラスを作成します.
public class FactoryProvider {
    public static AbstractFactory getFactory(String choice){
        
        if("Animal".equalsIgnoreCase(choice)){
            return new AnimalFactory();
        }
        else if("Color".equalsIgnoreCase(choice)){
            return new ColorFactory();
        }
        
        return null;
    }
}

Javaでの抽象ファクトリメソッドの使用例


JDKでは、DocumentBuilder Factoryクラスの新しいInstanceメソッドが抽象ファクトリメソッドモードの例です.DocumentBuilder Factoryは、xmlファイルをDocumentにパケット化するためのサンプルコードです.
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;

public class DocumentBuilderExample {
  public static void main(String[] args) throws Exception {
    String testXml = "<note><to>Receiver</to><from>Sender</from><heading>SubjectHeading</heading><body>Body text under the body tag.</body></note>";
    
    ByteArrayInputStream ba = new ByteArrayInputStream(testXml.getBytes());
    
    DocumentBuilderFactory absFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder factory = absFactory.newDocumentBuilder();
    Document doc = factory.parse(ba);
    doc.getDocumentElement().normalize();
    
    System.out.println("Root Node Name is ::: " + doc.getDocumentElement().getNodeName());
    System.out.println("get abstract factory class name is ::: " + absFactory.getClass());
    System.out.println("get abstract factory class name is ::: " + factory.getClass());
  }
}
DocumentBuilder Factoryはシステムのプロパティを読み込むことでインスタンスを作成するので、クライアントの観点から内部実装を知る必要はなく、newInstance()メソッドでファクトリを作成するだけです.
public abstract class DocumentBuilderFactory {
//.....
    public static DocumentBuilderFactory newInstance() {
        return FactoryFinder.find(
                /* The default property name according to the JAXP spec */
                DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
                /* The fallback implementation class name */
                DEFAULT_IMPL);
//.....
    }

}
FactoryFinderのfindメソッドに従って、3つのブランチがインスタンスを作成しています.
    static <T> T find(Class<T> type, String fallbackClassName)
        throws FactoryConfigurationError
    {
        final String factoryId = type.getName();
        dPrint(()->"find factoryId =" + factoryId);

        // Use the system property first
        try {
            String systemProp = SecuritySupport.getSystemProperty(factoryId);
            if (systemProp != null) {
                dPrint(()->"found system property, value=" + systemProp);
                return newInstance(type, systemProp, null, true);
            }
        }
}
システム属性がnullでない場合、システム属性はインスタンスを作成しています.
        try {
            if (firstTime) {
                synchronized (cacheProps) {
                    if (firstTime) {
                        String configFile = SecuritySupport.getSystemProperty("java.home") + File.separator +
                            "conf" + File.separator + "jaxp.properties";
                        File f = new File(configFile);
                        firstTime = false;
                        if (SecuritySupport.doesFileExist(f)) {
                            dPrint(()->"Read properties file "+f);
                            cacheProps.load(SecuritySupport.getFileInputStream(f));
                        }
                    }
                }
            }
            final String factoryClassName = cacheProps.getProperty(factoryId);

            if (factoryClassName != null) {
                dPrint(()->"found in ${java.home}/conf/jaxp.properties, value=" + factoryClassName);
                return newInstance(type, factoryClassName, null, true);
            }
        }
システム属性がnullの場合、$javaです.home/conf/jaxp.propertiesは、パスの設定を読み込むことでインスタンスを作成しようとします.
        T provider = findServiceProvider(type);
        if (provider != null) {
            return provider;
        }
        if (fallbackClassName == null) {
            throw new FactoryConfigurationError(
                "Provider for " + factoryId + " cannot be found");
        }

        dPrint(()->"loaded from fallback value: " + fallbackClassName);
        return newInstance(type, fallbackClassName, null, true);
最後に、Jar Service Providerを見つけてProviderに戻るか、Providerがない場合は、newInstance()を呼び出すときにデフォルトでDEFAULT IMPLに設定されます.
    private static final String DEFAULT_IMPL =
            "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl";
DocumentBuilder FactoryImplを作成して返します.

n/a.結論


オブジェクトをカプセル化して作成し、コードを構想フォーマットから分離します.これは、アプリケーションの組合せを緩和し、特定の実装への依存性を低減するのに役立ちます.