ConcreteAggregate は String 配列の集合オブジェクトを持ちますが、Iterator のインターフェース
によってそれを意識せずに順次アクセスすることができます。
void client() {
Aggregate aggregate = new ConcreteAggregate("aaa", "bbb", "ccc");
System.out.println("// Iterator 未使用");
String[] list = ((ConcreteAggregate)aggregate).list;
for (int i = 0; i < list.length; ++ i) {
System.out.print(list[i] + ", ");
}
System.out.println();
System.out.println("// Iterator 使用");
Iterator iterator = aggregate.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + ", ");
}
System.out.println();
}
interface Aggregate {
public Iterator iterator();
}
interface Iterator {
public boolean hasNext();
public String next();
}
class ConcreteAggregate implements Aggregate {
public String[] list;
public ConcreteAggregate(String... strings) {
this.list = strings;
}
public Iterator iterator() {
return new ConcreteIterator(this);
}
}
class ConcreteIterator implements Iterator {
private ConcreteAggregate aggregate;
private int index = 0;
public ConcreteIterator(ConcreteAggregate aggregate) {
this.aggregate = aggregate;
}
public boolean hasNext() {
return (this.index < this.aggregate.list.length);
}
public String next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
}
return this.aggregate.list[this.index ++];
}
}
出力結果:// Iterator 未使用
aaa, bbb, ccc,
// Iterator 使用
aaa, bbb, ccc,
サンプルプログラムとして、DOM ノードの子供のノードを Iterator パターンで実装する例を示します。
Iterator インターフェースとして標準ライブラリの Iterator インターフェースを、
同様に Aggregate は Iterable を使用しています。また、Iterable インターフェースを実装する
ことで、順次アクセスに foreach 文を使用することができます。
出力結果:
// Iterator パターン未使用
<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>
// Iterator パターン使用
<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>
// Iterator パターン使用 + foreach
<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.util.Iterator;
import java.util.NoSuchElementException;
/**
* Iterator
* GoF, Code Complete
*
* 集合オブジェクトの内部を公開せずに、要素への順次にアクセスする方法を提供します。
*
* @author 2015/05/29 matsushima
*/
public class IteratorSample {
/**
* main
*
* @param args
*/
public static void main(String[] args) {
new IteratorSample().client();
}
/**
* client
*/
void client() {
Document_ConcreteAggregate document = new Document_ConcreteAggregate();
Element_ConcreteAggregate root = document.createElement("root");
document.appendChild(root);
root.appendChild(document.createTextNode("\n "));
Element_ConcreteAggregate element;
root.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/"));
root.appendChild(document.createTextNode("\n "));
root.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/"));
root.appendChild(document.createTextNode("\n "));
root.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/"));
root.appendChild(document.createTextNode("\n"));
System.out.println("// Iterator パターン未使用");
printNode("node", document.getDocumentElement());
System.out.println();
System.out.println("// Iterator パターン使用");
printNode("iterator", document.getDocumentElement());
System.out.println();
System.out.println("// Iterator パターン使用 + foreach");
printNode("iterable", document.getDocumentElement());
}
/**
* ノードを出力。
*/
void printNode(String method, Node_Aggregate node) {
if (node instanceof Text_ConcreteAggregate) {
System.out.print(node.getNodeValue());
} else {
System.out.print("<" + node.getNodeName() + ">");
}
if ("node".equals(method)) {
for (Node_Aggregate child = node.getFirstChild();
null != child; child = child.getNextSibling()) {
this.printNode(method, child);
}
} else if ("iterator".equals(method)) {
for (Iterator<Node_Aggregate> it = node.iterator(); it.hasNext(); ) {
this.printNode(method, it.next());
}
} else if ("iterable".equals(method)) {
for (Node_Aggregate child: node) {
this.printNode(method, child);
}
}
if (node instanceof Text_ConcreteAggregate) {
} else {
System.out.print("</" + node.getNodeName() + ">");
}
}
/*
// Iterator
package java.util;
public interface Iterator<E> {
boolean hasNext();
E next();
void remove();
}
// Aggregate
package java.lang;
import java.util.Iterator;
public interface Iterable<T> {
Iterator<T> iterator();
}
*/
/** Aggregate: Node インターフェース。 */
public interface Node_Aggregate extends Iterable<Node_Aggregate> {
public String getNodeName();
public String getNodeValue();
public Node_Aggregate getFirstChild();
public Node_Aggregate getNextSibling();
public Node_Aggregate appendChild(Node_Aggregate node);
//public Iterator<Node> iterator(); // Iterable<Node>
}
/** ConcreteAggregate: Node 抽象クラス。 */
public abstract class AbstractNode_ConcreteAggregate implements Node_Aggregate {
private Node_Aggregate firstChild = null, lastChild = null, nextSibling = null;
public Node_Aggregate getFirstChild() { return this.firstChild; }
public Node_Aggregate getNextSibling() { return this.nextSibling; }
public Node_Aggregate appendChild(Node_Aggregate node) {
if (null == this.firstChild) { this.firstChild = node; }
if (null != this.lastChild) {
((AbstractNode_ConcreteAggregate)this.lastChild).nextSibling = node; }
this.lastChild = node;
return node;
}
public Iterator<Node_Aggregate> iterator() {
return new Node_ConcreteIterator();
}
/** ConcreteIterator: Node の Iterator。 */
private class Node_ConcreteIterator implements Iterator<Node_Aggregate> {
private Node_Aggregate node = firstChild;
public boolean hasNext() {
return (null != this.node);
}
public Node_Aggregate next() {
if (!this.hasNext()) {
throw new NoSuchElementException();
}
Node_Aggregate result = this.node;
this.node = this.node.getNextSibling();
return result;
}
public void remove() {
throw new UnsupportedOperationException();
}
}
}
/** ConcreteAggregate: Text。 */
public class Text_ConcreteAggregate extends AbstractNode_ConcreteAggregate {
private String value;
public Text_ConcreteAggregate(String value) { this.value = value; }
public String getNodeName() { return "#text"; }
public String getNodeValue() { return this.value; }
}
/** ConcreteAggregate: Element。 */
public class Element_ConcreteAggregate extends AbstractNode_ConcreteAggregate {
private String name;
public Element_ConcreteAggregate(String name) { this.name = name; }
public String getNodeName() { return this.name; }
public String getNodeValue() { return null; }
}
/** ConcreteAggregate: Document。 */
public class Document_ConcreteAggregate extends AbstractNode_ConcreteAggregate {
public String getNodeName() { return "#document"; }
public String getNodeValue() { return null; }
public Element_ConcreteAggregate getDocumentElement() {
return (Element_ConcreteAggregate)this.getFirstChild();
}
public Element_ConcreteAggregate createElement(String name) {
return new Element_ConcreteAggregate(name);
}
public Text_ConcreteAggregate createTextNode(String value) {
return new Text_ConcreteAggregate(value);
}
}
}
0 件のコメント:
コメントを投稿