zoukankan      html  css  js  c++  java
  • 设计模式(十一)解释器模式

    模式代码

    // 抽象表达式
    public abstract class AbstractExpression {
        /**
         * 抽象的解析方法
         */
        public abstract void interpret(Context ctx);
    }
    
    // 终结符表达式
    public class TerminalExpression extends AbstractExpression {
        @Override
        public void interpret(Context ctx) {
            //实现文法中与终结符有关的解释操作
        }
    }
    
    // 非终结符表达式
    public class NonterminalExpression extends AbstractExpression {
        @Override
        public void interpret(Context ctx) {
            //实现文法中与非终结符有关的解释操作
        }
    }
    
    // 上下文环境类,包含解释器之外的全局信息
    public class Context {
    }
    
    // 客户类
    public class Client {
        public static void main(String[] args) {
            //根据文法对特定句子构建抽象语法树后解释
        }
    }

    简单实现

    需求:比如算数表达式 m + n + p。代表数字的m、n、p三个字符看成终结符号,+ 看做非终结符号。

    1.抽象的算术运算解释器,为所有解释器共性的提取

    public abstract class ArithmeticExpression {
        /**
         * 抽象的解析方法
         * 具体的解析逻辑由具体的子类实现
         * @return 解析得到具体的值
         */
        public abstract int interpret();
    }

    2.数字解释器,仅仅为了解释数字

    public class NumExpression extends ArithmeticExpression{
        private int num;
    
        public NumExpression(int num) {
            this.num = num;
        }
    
        @Override
        public int interpret() {
            return num;
        }
    }

    3.运算符号抽象解释器,为所有运算符号解释器共性的提取

    public abstract class OperatorExpression extends ArithmeticExpression {
        //声明两个成员变量存储运算符号两边的数字解释器
        protected ArithmeticExpression exp1, exp2;
    
        public OperatorExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) {
            this.exp1 = exp1;
            this.exp2 = exp2;
        }
    }

    4.加法运算抽象解释器

    public class AdditionExpression extends OperatorExpression {
        public AdditionExpression(ArithmeticExpression exp1, ArithmeticExpression exp2) {
            super(exp1, exp2);
        }
    
        @Override
        public int interpret() {
            return exp1.interpret() + exp2.interpret();
        }
    }

    5.处理与解释相关的一些业务

    public class Calculator {
        //声明一个Stack栈存储并操作所有相关的解释器
        private Stack<ArithmeticExpression> mExpStack = new Stack<>();
    
        public Calculator(String expression) {
            //声明两个TerminalExpression类型的临时变量,存储运算符左右两边的数字解释器
            ArithmeticExpression exp1, exp2;
    
            String[] elements = expression.split(" ");
    
            //循环遍历表达式元素数组
            for (int i = 0; i < elements.length; i++) {
                //判断运算符号
                switch (elements[i].charAt(0)) {
                    case '+':   //如果是加号
                        //将栈中的解释器弹出作为运算符号右边的解释器
                        exp1 = mExpStack.pop();
                        //同时将运算符号数组下标下一个元素构造为一个数字解释器
                        exp2 = new NumExpression(Integer.valueOf(elements[++i]));
                        //通过尚明两个数字解释器构造加法运算解释器
                        mExpStack.push(new AdditionExpression(exp1, exp2));
                        break;    
                    default:    //如果是数字
                        //直接构造数字解释器并压入栈
                        mExpStack.push(new NumExpression(Integer.valueOf(elements[i])));
                        break;
                }
            }
        }
    
        public int calculate() {
            return mExpStack.pop().interpret();
        }
    }

    6.客户类

    public class Client {
        public static void main(String[] args) {
            Calculator calculator = new Calculator("1 + 2 + 3 + 10");
            System.out.println(calculator.calculate());
        }
    }

    此时只是定义了加法运算,如果需要增加减法运算,则可以在 Calculator 中增加以下分支

    case '-':   //如果是减号
        exp1 = mExpStack.pop();
        exp2 = new NumExpression(Integer.valueOf(elements[++i]));
        mExpStack.push(new SubtractionExpression(exp1, exp2));
        break;

    此时,在 Client 中就可以开始使用了

    public class Client {
        public static void main(String[] args) {
            Calculator calculator = new Calculator("1 - 2 - 3 + 10");
            System.out.println(calculator.calculate());
        }
    }
  • 相关阅读:
    LLVM 3.0 — LinuxTOY
    Fabric Engine 1.0
    tmux:GNU screen 替代品 — LinuxTOY
    LuoYun 开源云计算平台软件 0.2 Beta 版本发布 — LinuxTOY
    迅雷离线下载脚本 — LinuxTOY
    Vim 状态栏是 Powerline 插件。
    LuoYun 云计算平台 0.4 版本 liveCD 发布
    webOS Isis 开源 — LinuxTOY
    Impress.js — LinuxTOY
    从 screen 切换到 tmux — LinuxTOY
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/7816524.html
Copyright © 2011-2022 走看看