声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客http://chjavach.iteye.com/
package design.pattern;
/*
* 解释器(Interpreter)模式的意图是可以按照自己定义的组合规则集合来组合可执行对象
*
* 代码示例实现XML里面1.读取单个元素的值 2.读取单个属性的值
* 多个元素或者多个属性的示例书上也有,但稍显复杂,就不做这方面的笔记了
*/
import java.util.ArrayList;
import java.util.Collection;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
abstract class Expression {
//可能返回一个String也可能返回多个。String书上说为了兼容,返回值定义为String数组
public abstract String[] interpret(Context context);
}
/**
* Context持有两个Field:
* 1.整个XML对象(Document document)
* 2.上一个被处理的元素(Element preElement)
* 当Expression执行interpret方法时,不断改变Context里的preElement,直到表达式终止为止
*/
class Context {
//上一个被处理的元素
private Element preElement;
private Document document;
public Context(String filePath) throws Exception {
this.document = XMLUtil.getRoot(filePath);
}
public void redoInit() {
this.preElement = null;
}
/**
* 根据父元素和子元素的名字来获取子元素
* @param preElement 父元素
* @param elementName 要找的元素的名字
* @return 找到的元素
*/
public Element getCurElement(Element preElement, String elementName) {
Element result = null;
NodeList nodeList = preElement.getChildNodes();
//遍历所有直接子元素(孙子元素不算)
for (int i = 0, len = nodeList.getLength(); i < len ;i ++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
Element element = (Element)node;
if (element.getNodeName().equals(elementName)) {
result = element;
break;
}
}
}
return result;
}
public Element getPreElement() {
return preElement;
}
public void setPreElement(Element preElement) {
this.preElement = preElement;
}
public Document getDocument() {
return document;
}
}
/**
* 读取XML文件的帮助类。提供一个方法根据文件名返回XML Document对象
*/
class XMLUtil {
public static Document getRoot(String filePath) throws Exception {
Document doc = null;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
doc = builder.parse(filePath);
doc.normalize();
return doc;
}
}
//非终结元素的解释器
class ElementExpression extends Expression {
//在下面的测试,Expression的childExpressions只有一个。childExpressions.size() = 1
private Collection<Expression> childExpressions = new ArrayList<Expression>();
private String elementName;
public ElementExpression(String elementName) {
this.elementName = elementName;
}
public void add(Expression expression) {
this.childExpressions.add(expression);
}
public void remove(Expression expression) {
this.childExpressions.remove(expression);
}
public String[] interpret(Context context) {
Element parent = context.getPreElement();
Element curElement = null;
if (parent == null) { //说明是根元素
Document dom = context.getDocument();
curElement = dom.getDocumentElement(); //Document.getDocumentElement,取得根元素
} else {
curElement = context.getCurElement(parent, elementName);
}
context.setPreElement(curElement);
String[] ss = null;
for (Expression expression : childExpressions) {
//这里写得有歧义。如果childExpressions.size > 1,那ss只能获取到最后一个childExpression的返回值
//不过由于测试过程中,childExpressions.size = 1,也就问题不大
ss = expression.interpret(context);
}
return ss;
}
public String toString() {
return "elementName = " + elementName + ", childExpressions = " + childExpressions;
}
}
//元素作为终结符的解释器
class ElementTerminatorExpression extends Expression {
private String elementName;
public ElementTerminatorExpression(String elementName) {
this.elementName = elementName;
}
public String[] interpret(Context context) {
Element parent = context.getPreElement();
Element curElement = null;
if (parent == null) { //说明是根元素
curElement = context.getDocument().getDocumentElement(); //返回根元素
} else {
curElement = context.getCurElement(parent, elementName);
}
context.setPreElement(curElement);
//获取元素的值
String finalValue = curElement.getFirstChild().getNodeValue();
return new String[]{finalValue};
}
}
//属性作为终结符的解释器
class PropertyTerminatorExpression extends Expression {
private String propertyName;
public PropertyTerminatorExpression(String propertyName) {
this.propertyName = propertyName;
}
public String[] interpret(Context context) {
//直接获取元素的属性的值
String finalValue = context.getPreElement().getAttribute(this.propertyName);
return new String[]{finalValue};
}
}
//这个类是用来测试的
public class InterpreterPattern {
public static void main(String[] args) throws Exception {
/*
<?xml version="1.0" encoding="UTF-8"?>
<root id="rootId">
<a>
<b>
<c name="testC">12345</c>
<d id="1">d1</d>
<d id="2">d2</d>
<d id="3">d3</d>
<d id="4">d4</d>
</b>
</a>
</root>
*/
Context context = new Context("d:/interpretPattern.xml");
//构建要查找的表达式的语法树,例如我们要查看元素c的值,表达式是root/a/b/c
//元素作为终结符
ElementExpression root = new ElementExpression("root");
ElementExpression a = new ElementExpression("a");
ElementExpression b = new ElementExpression("b");
ElementTerminatorExpression c = new ElementTerminatorExpression("c");
root.add(a);
a.add(b);
b.add(c);
String[] ss = root.interpret(context);
System.out.println("c = " + ss[0]);
//元素属性作为终结符,例如root/a/b/c.name
context.redoInit();
ElementExpression roott = new ElementExpression("root");
ElementExpression aa = new ElementExpression("a");
ElementExpression bb = new ElementExpression("b");
ElementExpression cc= new ElementExpression("c");
PropertyTerminatorExpression prop = new PropertyTerminatorExpression("name");
roott.add(aa);
aa.add(bb);
bb.add(cc);
cc.add(prop);
ss = roott.interpret(context);
System.out.println("c name = " + ss[0]);
context.redoInit();
ss = roott.interpret(context);
System.out.println("c name = " + ss[0]);
}
}