1つのサブシステムが複数のクラスからなる場合、Client からは直接クラスにアクセスせずに、
Facade クラスのインターフェースを介して機能を利用します。
システムが複数のサブシステムからなる場合、サブシステム間の依存度を減らすことができます。
void client() {
new Facade().operation();
}
class Facade {
ComponentA componentA = new ComponentA();
ComponentB componentB = new ComponentB();
ComponentC componentC = new ComponentC();
public void operation() {
this.componentA.operationA();
this.componentB.operationB();
this.componentC.operationC();
}
}
class ComponentA {
public void operationA() {
System.out.println("A");
}
}
class ComponentB {
public void operationB() {
System.out.println("B");
}
}
class ComponentC {
public void operationC() {
System.out.println("C");
}
}
出力結果:A
B
C
サンプルプログラムとして、CSV から XML へ変換するコンバータを示します。
Facade パターンでは、Facade クラスのインターフェースを介してサブシステムにアクセスし、
サブシステム内には、パーサ、ジェネレータ、ノードなどのクラスがありますが、
直接アクセスすることはありません。
出力結果:
// CSV -> XML コンバート
<root>
<entry><name>Google</name><URL>http://www.google.co.jp/</URL></entry>
<entry><name>Yahoo</name><URL>http://www.yahoo.co.jp/</URL></entry>
<entry><name>bing</name><URL>http://www.bing.com/</URL></entry>
</root>
// CSV -> XML コンバータ。(Facade パターン)
<root>
<entry><name>Google</name><URL>http://www.google.co.jp/</URL></entry>
<entry><name>Yahoo</name><URL>http://www.yahoo.co.jp/</URL></entry>
<entry><name>bing</name><URL>http://www.bing.com/</URL></entry>
</root>
package design_pattern;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.util.LinkedList;
import java.util.List;
/**
* Facade パターン
* GoF, Code Complete
* サブシステム中のインターフェースのセットへの統一されたインターフェースを提供します。
*
* @author 2015/05/26 matsushima
*/
public class FacadeSample {
/**
* main
*
* @param args
*/
public static void main(String[] args) {
try {
new FacadeSample().client();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* Client
*/
void client() throws IOException {
String csvText =
"name,URL\n"
+ "Google,http://www.google.co.jp/\n"
+ "Yahoo,http://www.yahoo.co.jp/\n"
+ "bing,http://www.bing.com/\n"
;
System.out.println("// CSV -> XML コンバート");
// CSV パーサ。
CsvParser_Component parser = new CsvParser_Component();
Document_Component document = parser.parse(new StringReader(csvText));
// XML で出力。
XmlGenerator_Component generator = new XmlGenerator_Component();
generator.print(new OutputStreamWriter(System.out), document);
System.out.println("// CSV -> XML コンバータ。(Facade パターン)");
new CsvToXmlConverter_Facade().convert(
new StringReader(csvText),
new OutputStreamWriter(System.out));
}
/** CSV -> XML コンバータ。 */
public class CsvToXmlConverter_Facade {
public void convert(Reader in, Writer out) throws IOException {
// CSV パーサ。
CsvParser_Component parser = new CsvParser_Component();
Document_Component document = parser.parse(in);
// XML で出力。
XmlGenerator_Component generator = new XmlGenerator_Component();
generator.print(out, document);
}
}
/** CSV パーサ。 */
public class CsvParser_Component {
public Document_Component parse(Reader in) throws IOException {
Document_Component document = new Document_Component("root");
BufferedReader reader = new BufferedReader(in);
String line = reader.readLine();
String[] names = (null == line ? null : line.split(","));
while (null != (line = reader.readLine())) {
String[] cols = line.split(",");
Node_Component entry = document.appendChild(new Element_Component("entry"));
for (int i = 0; i < Math.min(names.length, cols.length); ++ i) {
entry.appendChild(new Element_Component(names[i]))
.appendChild(new Text_Component(cols[i]));
}
}
return document;
}
}
/** XML で出力。 */
public class XmlGenerator_Component {
public void print(Writer writer, Document_Component document) throws IOException {
this.printNodeImpl(new PrintWriter(writer), document, "");
writer.flush();
}
private void printNodeImpl(PrintWriter writer, Node_Component node, String indent) {
if (node instanceof Text_Component) {
writer.print(node.getNodeValue());
} else {
String r2 = (2 == indent.length() ? "\n" + indent : "");
String r0 = (0 == indent.length() ? "\n" : "");
writer.print(r2 + "<" + node.getNodeName() + ">");
for (Node_Component child: node.getChildNodes()) {
this.printNodeImpl(writer, child, indent + " ");
}
writer.print(r0 + "</" + node.getNodeName() + ">" + r0);
}
}
}
/** Node Component インターフェース。 */
public interface Node_Component {
public String getNodeName();
public String getNodeValue();
public Node_Component appendChild(Node_Component node);
public List<Node_Component> getChildNodes();
}
/** Text Component クラス。 */
public class Text_Component implements Node_Component {
private String value;
protected Text_Component(String value) { this.value = value; }
public String getNodeName() { return "#text"; }
public String getNodeValue() { return this.value; }
public Node_Component appendChild(Node_Component node) { return null; }
public List<Node_Component> getChildNodes() { return null; }
}
/** Element Component クラス。 */
public class Element_Component implements Node_Component {
private String name;
private LinkedList<Node_Component> children = new LinkedList<>();
protected Element_Component(String name) { this.name = name; }
public String getNodeName() { return this.name; }
public String getNodeValue() { return null; }
public Node_Component appendChild(Node_Component node) {
this.children.add(node);
return node;
}
public List<Node_Component> getChildNodes() {
return this.children;
}
}
/** Document Component クラス。 */
public class Document_Component implements Node_Component {
private String name;
private LinkedList<Node_Component> children = new LinkedList<>();
protected Document_Component(String name) { this.name = name; }
public String getNodeName() { return this.name; }
public String getNodeValue() { return null; }
public Node_Component appendChild(Node_Component node) {
this.children.add(node);
return node;
}
public List<Node_Component> getChildNodes() {
return this.children;
}
public Element_Component createElement(String name) { return new Element_Component(name); }
public Text_Component createTextNode(String value) { return new Text_Component(value); }
}
}
0 件のコメント:
コメントを投稿