一般的に関連するインスタンス群を生成するには、new Product1(); new Product2(); ...
のように直接クラスを指定して new します。
Abstract Factory パターンでは、これらを行う Factory クラスを用意し、このクラスのメソッドを介してインスタンス群の生成を行います。
サンプルでは、DOM ツリーを構築し、XML または Json で出力する例を示します。
package design_pattern;
import java.io.PrintStream;
import java.util.LinkedList;
/**
* Abstract Factory
* GoF, Code Complete
* お互いに関連・依存するクラス群を、別途生成するためのインターフェースを提供します。
*
* 一般的に関連するインスタンス群を生成するには、new Product1(); new Product2(); ...
* のように直接クラスを指定して new します。
* Abstract Factory パターンでは、これらを行う Factory クラスを用意し、
* このクラスのメソッドを介してインスタンス群の生成を行います。
*
出力結果:
// Abstract Factory 未使用
<pc>
<cpu>
<name>
Core i5
</name>
<clock>
2GHz
</clock>
</cpu>
<memory>
<name>
DDR2
</name>
<capacity>
2GB
</capacity>
</memory>
</pc>
// Abstract Factory 使用
<pc>
<cpu>
<name>
Core i7
</name>
<clock>
3GHz
</clock>
</cpu>
<memory>
<name>
DDR3
</name>
<capacity>
4GB
</capacity>
</memory>
</pc>
*
* @author 2015/05/22 matsushima
*/
public class AbstranctFactorySample {
/**
* main
*
* @param args
*/
public static void main(String[] args) {
new AbstranctFactorySample().client(args.length >= 1 ? args[0] : "xml");
}
/**
* Client
*/
void client(String type) {
/*
* 一般的に関連するインスタンス群を生成するには、new Product1(); new Product2();
* ... のように直接クラスを指定して new します。
*/
System.out.println("// Abstract Factory 未使用");
if ("xml".equals(type)) {
XmlElement_ConcreateProduct e1, e2, e3;
e1 = new XmlElement_ConcreateProduct("pc");
e1.appendChild(e2 = new XmlElement_ConcreateProduct("cpu"));
e2.appendChild(e3 = new XmlElement_ConcreateProduct("name"));
e3.appendChild(new XmlText_ConcreateProduct("Core i5"));
e2.appendChild(e3 = new XmlElement_ConcreateProduct("clock"));
e3.appendChild(new XmlText_ConcreateProduct("2GHz"));
e1.appendChild(e2 = new XmlElement_ConcreateProduct("memory"));
e2.appendChild(e3 = new XmlElement_ConcreateProduct("name"));
e3.appendChild(new XmlText_ConcreateProduct("DDR2"));
e2.appendChild(e3 = new XmlElement_ConcreateProduct("capacity"));
e3.appendChild(new XmlText_ConcreateProduct("2GB"));
e1.printNode(System.out, "");
} else if ("json".equals(type)) {
JsonElement_ConcreateProduct e1, e2, e3;
e1 = new JsonElement_ConcreateProduct("pc");
e1.appendChild(e2 = new JsonElement_ConcreateProduct("cpu"));
e2.appendChild(e3 = new JsonElement_ConcreateProduct("name"));
e3.appendChild(new JsonText_ConcreateProduct("Core i5"));
e2.appendChild(e3 = new JsonElement_ConcreateProduct("clock"));
e3.appendChild(new JsonText_ConcreateProduct("2GHz"));
e1.appendChild(e2 = new JsonElement_ConcreateProduct("memory"));
e2.appendChild(e3 = new JsonElement_ConcreateProduct("name"));
e3.appendChild(new JsonText_ConcreateProduct("DDR2"));
e2.appendChild(e3 = new JsonElement_ConcreateProduct("capacity"));
e3.appendChild(new JsonText_ConcreateProduct("2GB"));
e1.printNode(System.out, "");
} else {
throw new UnsupportedOperationException(type);
}
/*
* Abstract Factory パターンでは、これらを行う Factory クラスを用意し、
* このクラスのメソッドを介してインスタンス群の生成を行います。
*/
System.out.println("// Abstract Factory 使用");
Document_AbstractFactory document;
if ("xml".equals(type)) {
document = new XmlDocument_ConcreateFactory();
} else if ("json".equals(type)) {
document = new JsonDocument_ConcreateFactory();
} else {
throw new UnsupportedOperationException(type);
}
Element_AbstractProduct e1, e2, e3;
e1 = document.createElement("pc");
e1.appendChild(e2 = document.createElement("cpu"));
e2.appendChild(e3 = document.createElement("name"));
e3.appendChild(document.createTextNode("Core i7"));
e2.appendChild(e3 = document.createElement("clock"));
e3.appendChild(document.createTextNode("3GHz"));
e1.appendChild(e2 = document.createElement("memory"));
e2.appendChild(e3 = document.createElement("name"));
e3.appendChild(document.createTextNode("DDR3"));
e2.appendChild(e3 = document.createElement("capacity"));
e3.appendChild(document.createTextNode("4GB"));
e1.printNode(System.out, "");
}
/** Node Product インターフェース。 */
public interface Node_AbstractProduct {
public String getNodeName();
public String getNodeValue();
public void printNode(PrintStream writer, String indent);
}
/** Text Node Product 抽象クラス。 */
public abstract class Text_AbstractProduct implements Node_AbstractProduct {
private String value;
protected Text_AbstractProduct(String value) {
this.value = value;
}
public String getNodeName() {
return "#text";
}
public String getNodeValue() {
return this.value;
}
}
/** Element Node Product 抽象クラス。 */
public abstract class Element_AbstractProduct implements Node_AbstractProduct {
private String name;
private LinkedList<Node_AbstractProduct> children = new LinkedList<>();
protected Element_AbstractProduct(String name) {
this.name = name;
}
public String getNodeName() {
return this.name;
}
public String getNodeValue() {
return null;
}
public Node_AbstractProduct appendChild(Node_AbstractProduct node) {
this.children.add(node);
return node;
}
public Node_AbstractProduct removeChild(Node_AbstractProduct node) {
this.children.remove(node);
return node;
}
public Node_AbstractProduct getChild(int index) {
return index < this.children.size() ? this.children.get(index) : null;
}
}
/** XML Text Node Product。 */
public class XmlText_ConcreateProduct extends Text_AbstractProduct {
public XmlText_ConcreateProduct(String value) {
super(value);
}
@Override
public void printNode(PrintStream writer, String indent) {
writer.println(indent + this.getNodeValue());
}
}
/** Json Text Node Product。 */
public class JsonText_ConcreateProduct extends Text_AbstractProduct {
public JsonText_ConcreateProduct(String value) {
super(value);
}
@Override
public void printNode(PrintStream writer, String indent) {
writer.println(indent + this.getNodeValue());
}
}
/** XML Element Node Product。 */
public class XmlElement_ConcreateProduct extends Element_AbstractProduct {
public XmlElement_ConcreateProduct(String name) {
super(name);
}
@Override
public void printNode(PrintStream writer, String indent) {
writer.println(indent + "<" + this.getNodeName() + ">");
for (int i = 0; null != this.getChild(i); ++ i) {
this.getChild(i).printNode(writer, indent + " ");
}
writer.println(indent + "</" + this.getNodeName() + ">");
}
}
/** Json Element Node Product。 */
public class JsonElement_ConcreateProduct extends Element_AbstractProduct {
public JsonElement_ConcreateProduct(String name) {
super(name);
}
@Override
public void printNode(PrintStream writer, String indent) {
writer.println(indent + "{" + this.getNodeName() + ":");
indent = indent.replace(",", "");
for (int i = 0; null != this.getChild(i); ++ i) {
this.getChild(i).printNode(writer, indent + (0 == i ? " " : " ,"));
}
writer.println(indent + "}");
}
}
/** Node(Text, Element) を生成する Document Factory インターフェース。 */
public interface Document_AbstractFactory {
/** Element Node を生成する。 */
public Element_AbstractProduct createElement(String name);
/** Text Node を生成する。 */
public Text_AbstractProduct createTextNode(String text);
}
/** XML の Node(Text, Element) を生成する Document Factory。 */
public class XmlDocument_ConcreateFactory implements Document_AbstractFactory {
@Override
public Element_AbstractProduct createElement(String name) {
return new XmlElement_ConcreateProduct(name);
}
@Override
public Text_AbstractProduct createTextNode(String text) {
return new XmlText_ConcreateProduct(text);
}
}
/** Json の Node(Text, Element) を生成する Document Factory。 */
public class JsonDocument_ConcreateFactory implements Document_AbstractFactory {
@Override
public Element_AbstractProduct createElement(String name) {
return new JsonElement_ConcreateProduct(name);
}
@Override
public Text_AbstractProduct createTextNode(String text) {
return new JsonText_ConcreateProduct(text);
}
}
}