读《研磨设计模式》-代码笔记-解释器模式-Interpret

[b]声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客[url]http://chjavach.iteye.com/[/url][/b]


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]);
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值