2015年6月12日金曜日

1-11. Flyweight パターン

多数のオブジェクトを効率的にサポートするために共有を使用します。



オブジェクトを多数生成するとメモリを多く消費してしまいますが、
同じオブジェクトを共有化し再利用することで、効率化します。
ここでオブジェクトは、ほかの利用個所で影響しないように、生成されたあとに
状態が変化しない不変なオブジェクトである必要があります。
class FlyweightFactory {
	private HashMap<String, Flyweight> flyweights = new HashMap<>();
	public Flyweight getFlyWeight(String text) {
		Flyweight flyweight = this.flyweights.get(text);
		if (null == flyweight) {
			flyweight = new Flyweight(text);
			this.flyweights.put(text, flyweight);
		}
		return flyweight;
	}
}
class Flyweight {
	private String text;
	public Flyweight(String text) { this.text = text; }
	public String getText() { return this.text; }
}
void client() {
	FlyweightFactory factory = new FlyweightFactory();
	Flyweight f1 = factory.getFlyWeight("abc");
	Flyweight f2 = factory.getFlyWeight("123");
	Flyweight f3 = factory.getFlyWeight("abc");
	System.out.println(f1 + ": " + f1.getText());
	System.out.println(f2 + ": " + f2.getText());
	System.out.println(f3 + ": " + f3.getText());
}
出力結果:
design_pattern.FlyweightSample$Flyweight@6d14382d: abc
design_pattern.FlyweightSample$Flyweight@4a744a4d: 123
design_pattern.FlyweightSample$Flyweight@6d14382d: abc
サンプルプログラムとして、DOM ノードを構築する例を示します。
このうち、Text_Flyweight クラスの生成を、Flyweight パターンで実装しています。

出力結果:
<root>
  <entry><name>Google(147567651)</name><URL>http://www.google.co.jp/(1973381719)</URL></entry>
  <entry><name>Yahoo(889106965)</name><URL>http://www.yahoo.co.jp/(1029544929)</URL></entry>
  <entry><name>bing(1285877824)</name><URL>http://www.bing.com/(1620648207)</URL></entry>
</root>
package design_pattern;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

/**
 * Flyweight パターン
 * GoF
 * 多数のオブジェクトを効率的にサポートするために共有を使用します。
 * 
 * @author 2015/05/26 matsushima
 */
public class FlyweightSample {

	public static void main(String[] args) {
		new FlyweightSample().client();
	}

	void client() {
		Document_FlyweightFactory document = new Document_FlyweightFactory("root");
		Element element;
		document.appendChild(element = document.createElement("entry"));
		element.appendChild(document.createElement("name"))
				.appendChild(document.createTextNode("Google"));
		element.appendChild(document.createElement("URL"))
				.appendChild(document.createTextNode("http://www.google.co.jp/"));
		document.appendChild(element = document.createElement("entry"));
		element.appendChild(document.createElement("name"))
				.appendChild(document.createTextNode("Yahoo"));
		element.appendChild(document.createElement("URL"))
				.appendChild(document.createTextNode("http://www.yahoo.co.jp/"));
		document.appendChild(element = document.createElement("entry"));
		element.appendChild(document.createElement("name"))
				.appendChild(document.createTextNode("bing"));
		element.appendChild(document.createElement("URL"))
		.appendChild(document.createTextNode("http://www.bing.com/"));
		printNodeImpl(document, "");
	}
	void printNodeImpl(Node node, String indent) {
		if (node instanceof Text_Flyweight) {
			System.out.print(node.getNodeValue() + "(" + node.hashCode() + ")");
		} else {
			String r2 = (2 == indent.length() ? "\n" + indent : "");
			String r0 = (0 == indent.length() ? "\n" : "");
			System.out.print(r2 + "<" + node.getNodeName() + ">");
			for (Node child: node.getChildNodes()) {
				this.printNodeImpl(child, indent + "  ");
			}
			System.out.print(r0 + "</" + node.getNodeName() + ">" + r0);
		}
	}
	
	/** Node インターフェース。 */
	public interface Node {
		public String getNodeName();
		public String getNodeValue();
		public Node appendChild(Node node);
		public List<Node> getChildNodes();
	}
	/** Text Flyweight クラス。 */
	public class Text_Flyweight implements Node {
		private String value;
		protected Text_Flyweight(String value) { this.value = value; }
		public String getNodeName() { return "#text"; }
		public String getNodeValue() { return this.value; }
		public Node appendChild(Node node) { return null; }
		public List<Node> getChildNodes() { return null; }
	}
	/** Element クラス。 */
	public class Element implements Node {
		private String name;
		private LinkedList<Node> children = new LinkedList<>();
		protected Element(String name) { this.name = name; }
		public String getNodeName() { return this.name; }
		public String getNodeValue() { return null; }
		public Node appendChild(Node node) {
			this.children.add(node);
			return node;
		}
		public List<Node> getChildNodes() {
			return this.children;
		}
	}
	/** Document Flyweight Factory クラス。 */
	public class Document_FlyweightFactory implements Node {
		private HashMap<String, Text_Flyweight> textFlyweights = new HashMap<>();
		private String name;
		private LinkedList<Node> children = new LinkedList<>();
		protected Document_FlyweightFactory(String name) { this.name = name; }
		public String getNodeName() { return this.name; }
		public String getNodeValue() { return null; }
		public Node appendChild(Node node) {
			this.children.add(node);
			return node;
		}
		public List<Node> getChildNodes() {
			return this.children;
		}
		public Element createElement(String name) {
			return new Element(name);
		}
		public Text_Flyweight createTextNode(String value) {
			Text_Flyweight node = this.textFlyweights.get(value);
			if (null == node) {
				node = new Text_Flyweight(value);
				this.textFlyweights.put(value, node);
			}
			return node;
		}
	}
}

0 件のコメント:

コメントを投稿