[设计模式]解释器模式

1. 定义

  给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

  这里的文法,就是我们通常所说的“语法规则”

2. 类图

  

3. 实例

  

package com.jerry.designpattern.demo;
/**
 * 用于处理自定义xml解释表达式的接口
 * @author Jerry
 * @date 2015年2月4日 下午10:24:41
 */
public abstract class ReadXmlExpression {
    /**
     * 解释表达式
     * @param expression
     * @return 为了通用,返回至可能存在一个或多个,统一使用数组返回
     */
    public abstract String[] interpret(Context c);
}

package com.jerry.designpattern.demo;

import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.Element;

/**
 * 元素非终止表达式
 * @author Jerry
 * @date 2015年2月4日 下午10:29:44
 */
public class ElementExpression extends ReadXmlExpression{
    private List<ReadXmlExpression> children = new ArrayList<>();

    private String eltName;

    public ElementExpression(String eltName) {
        this.eltName = eltName;
    }

    public void addElt(ReadXmlExpression elt) {
        this.children.add(elt);
    }

    public void removeElt(ReadXmlExpression elt) {
        this.children.remove(elt);
    }

    @Override
    public String[] interpret(Context c) {
        // TODO Auto-generated method stub
        Element preElt = c.getPreElt();

        if (preElt == null) {
            c.setPreElt(c.getDoc().getDocumentElement());
        } else {
            c.setPreElt(c.getNowElt(preElt, eltName));
        }

        String[] ss = null;

        for (ReadXmlExpression rxe: children) {
            ss = rxe.interpret(c);
        }

        return ss;
    }

}

package com.jerry.designpattern.demo;

import org.w3c.dom.Element;

/**
 * 元素终止表达式
 * @author Jerry
 * @date 2015年2月4日 下午10:53:42
 */
public class ElementTerminalException extends ReadXmlExpression{

    private String eltName;

    public ElementTerminalException(String eltName) {
        this.eltName = eltName;
    }

    @Override
    public String[] interpret(Context c) {
        // TODO Auto-generated method stub
//        Element preElt = c.getPreElt();
//        Element nowElt = c.getNowElt(preElt, this.eltName);
//
//        String[] ss = new String[1];
//        ss[0] = nowElt.getTextContent();
//        return ss;

        Element preElt = c.getPreElt();
        Element nowElt = null;
        if (preElt == null) {
            nowElt = c.getDoc().getDocumentElement();
            c.setPreElt(nowElt);
        } else {
            nowElt = c.getNowElt(preElt, this.eltName);
            c.setPreElt(nowElt);
        }
        String[] ss = new String[1];
        ss[0] = nowElt.getFirstChild().getNodeValue();
        return ss;
    }

}

package com.jerry.designpattern.demo;

import org.w3c.dom.Element;

/**
 * 属性终止表达式
 * @author Jerry
 * @date 2015年2月4日 下午10:56:57
 */
public class PropertyTerminalExpression extends ReadXmlExpression{
    private String propertyName;

    public PropertyTerminalExpression(String propertyName) {
        this.propertyName = propertyName;
    }

    @Override
    public String[] interpret(Context c) {
        // TODO Auto-generated method stub
        Element preElt = c.getPreElt();
        String value = preElt.getAttribute(propertyName);
        String[] ss = new String[1];
        ss[0] = value;
        return ss;
    }
}

package com.jerry.designpattern.demo;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 *
 * @author Jerry
 * @date 2015年2月4日 下午10:23:25
 */
public class Context {
    /**
     * 前一个元素
     */
    private Element preElt;

    /**
     * xml document
     */
    private Document doc;

    public Context(String fileName) throws Exception {
        this.doc = XMLUtils.getRoot(fileName);
    }

    /**
     * 根据父元素和当前元素名称,查找当前元素
     * @param pElt
     * @param eltName
     * @return
     */
    public Element getNowElt(Element pElt, String eltName) {
        Element elt = null;
        NodeList nodeList = pElt.getChildNodes();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node instanceof Element) {
                Element tempElt = (Element)node;
                if (tempElt.getTagName().equals(eltName)) {
                    elt = tempElt;
                    break;
                }
            }
        }
        return elt;
    }

    public void reInit() {
        this.doc = null;
    }

    public void setPreElt(Element preElt) {
        this.preElt = preElt;
    }

    public Element getPreElt() {
        return preElt;
    }

    public Document getDoc() {
        return doc;
    }
}

package com.jerry.designpattern.demo;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;

public class XMLUtils {
    public static Document getRoot(String fileName) throws Exception {
        Document doc = null;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        doc = builder.parse(fileName);
        doc.normalize();//去掉xml文档中作为格式化内容的空白而映射在Dom树种的TextNode对象
        return doc;
    }
}

package com.jerry.designpattern.demo;

/**
 *
 * @author Jerry
 * @date 2015年2月4日 下午10:59:37
 */
public class Client {
    public static void main(String[] args) throws Exception {
        Context ctx = new Context("interpret.xml");
        /**
         * 读取a/b/c c元素的值
         */
//        ElementExpression root = new ElementExpression("root");
//        ElementExpression aEltExp = new ElementExpression("a");
//        ElementExpression bEltExp = new ElementExpression("b");
//        ElementTerminalException cEltTeExp = new ElementTerminalException("c");
//        root.addElt(aEltExp);
//        aEltExp.addElt(bEltExp);
//        bEltExp.addElt(cEltTeExp);
        //String[] ss = root.interpret(ctx);
        //System.out.println("root/a/b/c c元素的值为:" + ss[0]);

        /**
         * 读取root/a/b/c c元素name属性的值
         */
        ElementExpression root = new ElementExpression("root");
        ElementExpression aEltExp = new ElementExpression("a");
        ElementExpression bEltExp = new ElementExpression("b");
        ElementExpression cEltExp = new ElementExpression("c");
        PropertyTerminalExpression proTerExp = new PropertyTerminalExpression("name");
        root.addElt(aEltExp);
        aEltExp.addElt(bEltExp);
        bEltExp.addElt(cEltExp);
        cEltExp.addElt(proTerExp);
        String[] ss = root.interpret(ctx);
        System.out.println("root/a/b/c c元素name属性的值为:" + ss[0]);
    }
}

4. 解释器模式的应用

  4.1 解释器的优点

    解释器是一个简单语法分析工具,最大的特点是其扩展性,修改语法规则只要修改相应的非终结点表达式,若增加语法,只需要增加相应的非终结点类就可以了

  4.2 解释器的缺点

    语法分析会引起类膨胀,解释采用递归方法,调试问题麻烦,而且存在效率问题。

时间: 2024-11-03 22:01:46

[设计模式]解释器模式的相关文章

PHP设计模式——解释器模式

声明:本系列博客参考资料<大话设计模式>,作者程杰. 解释器模式:Given a language, define arepresentation for its grammar along with an interpreter that uses therepresentation to interpret sentences in the language.给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 类图: 角色: 环境角色(Play

[设计模式] 解释器模式 Interpreter

在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子.这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题. 就如上面说的那个游戏,我输入up walk 5,我必须按照:移动方向+移动方式+移动距离这种格式输入我的指令,而这种格式的指令就是一种文法,只有按照了我定义的

深入浅出设计模式——解释器模式(Interpreter Pattern)

模式动机 如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题.解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中. 模式定义解释器模式(Interpreter Pattern) :定义语言的文法,并且建立一个解释器来解释该语言中的句子,这里的“语言”意思是使用规定格式和语法的代码,它是一种类行为型模式.Interpreter Pattern: Give

[工作中的设计模式]解释器模式模式Interpreter

一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我很少附上类图,但解释器模式确实比较抽象,为了便于理解还是放了上来,此模式的要点是: 1.客户端提供一个文本.表达式或者其他,约定解析格式 2.针对文本中可以分为终结符表达式和非终结符表达式, 3.终结符表达式无需进一步解析,但仍需要转化为抽象接口的实例 4.针对非终结表达式,没一种标示需要定义一种解

设计模式-解释器模式(行为模式)

概述: GOF定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 在软件开发特别是DSL开发中常常需要使用一些相对较复杂的业务语言,如果业务语言使用频率足够高,且使用普通的编程模式来实现会导致非常复杂的变化,那么就可以考虑使用解释器模式构建一个解释器对复杂的业务语言进行翻译. 这种做法虽然效率相对较低,但可以允许用户使用自定义的业务语言来处理逻辑,因此在效率不是关键问题的场合还是较为有用的. 1. context:包含解释器之外的一些全局信息.

设计模式--解释器模式C++实现

1定义 给定一门语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子 2类图 角色分析 AbstractExpression抽象解释器,具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression和NonterminalExpression完成 TerminalExpression终结符表达式,实现与文法中的元素相关的解释操作,通常一个解释器模式中只能有一个终结符表达式,但有多个实例,敌营不同的终结符 NonterminalExpress

JAVA 设计模式 解释器模式

用途 解释器模式 (Interpreter) 定义一个语言,定义它的文法的一种表示. 并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 解释器模式是一种行为型模式. 结构 图-解释器模式 Context : 包含解释器之外的一些全局信息. class Context {    private String input;    private String output;        public void setInput(String input) {        this.in

小菜学设计模式——解释器模式

背景 html在不同的浏览器都需要解析,这个解析过程就是解释器模式的体现. 1.使用意图 对有规律的句子进维护解析 2.生活实例 说到解析,就让我想到浏览器,IE浏览器直接就降低了我的工作效率,因为的他的怪异模式对html的解析确实很让人头疼.解释器模式的体现,就是四大浏览器(IE.谷歌.火狐.Safari)对html语言的解析上. 3.Java 例子(框架.JDK .JEE) 正则表达式 4.模式类图 抽象表达式(AbstractExpression): 声明一个抽象的解释方法. 终结符表达式

PHP设计模式 - 解释器模式

给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 角色: 环境角色(PlayContent):定义解释规则的全局信息. 抽象解释器(Empress):定义了部分解释具体实现,封装了一些由具体解释器实现的接口. 具体解释器(MusicNote):实现抽象解释器的接口,进行具体的解释执行. <?php class Expression { //抽象表示 function interpreter($str) { return $str; } } clas