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


    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 解释器的缺点

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

  • 相关阅读:
    R语言 逐步回归分析
    R语言 一元线性回归
    基于Qt的信号分析简单应用软件的设计
    【图论 5】图的应用——拓扑排序和关键路径
    【图论 3】图的应用——最小生成树
    B+树
    大概是最简明的B树博客了
    KMP算法
    【内存管理篇】基本分页存储管理方式
    双向链表为何时间复杂度为O(1)?
  • 原文地址:https://www.cnblogs.com/jerry19890622/p/4376483.html
Copyright © 2020-2023  润新知