`

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

阅读更多
声明:
本文只为方便我个人查阅和理解,详细的分析以及源代码请移步 原作者的博客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]);
    }

}


1
2
分享到:
评论

相关推荐

    设计模式专题之(二十二)解释模式---设计模式解释模式示例代码(python--c++)

    在标题和描述中提到的"设计模式专题之(二十二)解释模式",显然这是一个关于解释器模式的深入探讨,它提供了Python和C++两种语言的示例代码。解释器模式的应用场景包括简单的配置文件解析、小型脚本语言实现等,它...

    设计模式-解释器模式(讲解及其实现代码)

    **解释器模式**是一种行为设计模式,它提供了一种方式来表示语言的语法,并通过类和对象解析这种语法。在编程领域,解释器模式常用于创建简单的语言或表达式解析器,例如配置文件、计算器应用或者SQL查询的简化版本...

    韩顺平_Java设计模式笔记.docx

    - **Spring框架中解释器设计模式的应用**:Spring框架中的`SpelExpressionParser`使用了解释器模式,用于解析Spring表达式语言(SpEL)。 - **单例设计模式** - **实现方式**:单例模式共有8种实现方式,包括...

    java常用设计模式-解释器模式

    解释器模式是一种行为设计模式,它定义了一种语言和该语言的解释器,使得可以使用该语言来表达一些特定的操作。该模式适用于需要解释一些特定语言的场景,例如编译器、表达式计算器等。 在 Java 中,可以使用抽象...

    art-dex-interpret,在解释模式下加载艺术索引.zip

    总结来说,"art-dex-interpret"项目揭示了Android应用在解释模式下如何加载和执行代码,特别是关于艺术索引的构建和使用。这对于深入理解Android系统的运行机制,尤其是对性能敏感的开发者,具有很高的学习价值。...

    设计模式之解释器模式Java版本实现

    解释器模式是一种行为设计模式,它允许我们定义一个语言的语法,并提供一个解释器来解析该语言中的句子。在Java中实现解释器模式,我们可以创建一个抽象表达式接口,然后为每种特定的语法结构创建一个具体表达式类。...

    设计模式之解释器

    解释器模式是一种行为型设计模式,主要用于处理语言的文法规则、算术规则等问题。它通过定义语言的文法,并根据该文法来解释句子,使得我们可以用统一的方式处理各种语言结构。本文将通过具体的例子——加减运算来...

    设计模式之解释器模式(Interpreter Pattern)

    **设计模式之解释器模式(Interpreter Pattern)** 解释器模式是一种行为设计模式,它提供了一种方式来表示语言的语法,并实现一个解释器用于解析这种语法的语句。这种模式通常用于小型、特定领域的语言(DSL)实现,...

    设计模式之解释器模式(Interpreter)

    **解释器模式(Interpreter)**是一种行为设计模式,它允许我们定义一种语言并为其创建一个解释器。在软件工程中,这种模式常用于处理简单的语言或表达式,例如配置文件、计算公式或者简单的脚本语言。通过使用解释...

    cpp代码-设计模式-解释器模式

    **解释器模式**是一种行为设计模式,它允许我们定义一个语言的文法,并提供一个解释器来解析该文法中的句子。在C++编程中,解释器模式常用于处理简单的语言或表达式,例如配置文件、计算器表达式等。通过使用解释器...

    Python库 | interpret-community-0.6.0.tar.gz

    资源分类:Python库 所属语言:Python 资源全名:interpret-community-0.6.0.tar.gz 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    解释器模式代码示例

    解释器模式是一种设计模式,它允许我们为特定的语言或表达式定义一个解析规则,并提供一个解释器来执行这些规则。这种模式在处理简单的语言或结构化表达式时特别有用,例如配置文件、简单的数学表达式或者编程语言的...

    清华大学出版 基于java程序语言的java设计模式课程 18-解释器模式(共25页).pptx

    【解释器模式】是软件设计模式中的一种,属于类行为型模式。它的主要目的是为了创建一个解析器,这个解析器可以解释特定的语言或表达式。解释器模式通过定义文法来解析输入的句子,通常应用于构建小型的自定义语言...

    Android编程设计模式之解释器模式详解

    【Android编程设计模式之解释器模式详解】 解释器模式(Interpreter Pattern)是设计模式中的一种行为模式,主要用于解析特定语言或表达式。在Android开发中,尽管不常见,但当需要自定义简单的语言或者表达式解释...

    [行为型模式] 解释器模式的理解

    解释器模式是一种设计模式,它允许我们为特定语言创建一个解析器。这种模式在处理简单的语言或表达式时特别有用,例如配置文件、简单的编程语言或者数学表达式。解释器模式的核心在于构建一个抽象语法树(AST),...

    Python库 | interpret-0.0.5-py3-none-any.whl

    标题中的"interpret-0.0.5-py3-none-any.whl"是一个Python库的发行文件,这通常是一个可安装的Python包,用于扩展Python的功能。这个特定的包名为"interpret",版本号为0.0.5,适用于Python 3环境。"py3-none-any"是...

    设计模式_行为型_解释器模式.md

    解释器模式是设计模式中行为型的一种模式,它主要负责将特定的上下文(Context)中的语法规则转换成一个具体的对象。这种模式在编译原理、文本分析等领域有着广泛的应用。在解释器模式中,我们可以为一个特定的语言...

    解释器模式简介和java代码实现

    解释器模式详解与Java代码实现 解释器模式是一种行为型设计模式,它用于定义语言的文法,并解析和执行给定语言中的表达式。该模式将每个表达式表示为一个类,并提供了一种方式来组合这些表达式以实现复杂的语句。 ...

Global site tag (gtag.js) - Google Analytics