2015年6月12日金曜日

1-10. Facade パターン

サブシステム中のインターフェースのセットへの統一されたインターフェースを提供します。



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 件のコメント:

コメントを投稿