摘要:描述对一个表达式进行解释时,将表达式分为终结符非终结符运算环境,这样区分可以把表达式的各个部分独立出来扩展。
描述:对一个表达式进行解释时,将表达式分为终结符、非终结符、运算环境,这样区分可以把表达式的各个部分独立出来扩展。
名称解释:
表达式:一条运算语句,如c = a + b,它有一个解释方法,可以计算表达式结果
终结符:表达式中的变量,如a、b,终结符表达式负责解释终结符,即计算结果
非终结符:表达式中的运算符,如+,非终结符表达式负责计算非终结符的结果
运算环境:负责给终结符赋值,如a=1
场景:写个解释器,解释a+b=3,其中a=1,b=2,c=0,另外扩展一个相反数运算使-a=-1。
实现:
抽象一个表达式,负责解释终结符或者非终结符,其定义一个解释方法,计算表达式的值,同时覆盖equals和hashCode方法,方便判断两个表达式是否相同
abstract class Expression { String name; Expression(String name) { this.name = name; } abstract int interpret(Context ctx); @Override public boolean equals(Object obj) { if(null == obj) { return false; } if(obj instanceof String && name.equals(obj)) { return true; } return false; } @Override public int hashCode() { return name.hashCode(); } }
定义一个终结符表达式,也就是负责计算变量的值
class Variable extends Expression { Variable(String name) { super(name); } @Override int interpret(Context ctx) { return ctx.lookup(this); } }
定一个非终结符表达式,其名为加法,负责计算两个终结符的值
class AddExpression extends Expression { Expression var1; Expression var2; AddExpression(Expression var1, String name, Expression var2) { super(name); this.var1 = var1; this.var2 = var2; } @Override int interpret(Context ctx) { return var1.interpret(ctx) + var2.interpret(ctx); } }
如果想扩展一种运算,可以直接定义一个非终结符表达式,比如定义一个求相反数的运算
//一个数的相反数 class OppositeExpression extends Expression { Expression var; OppositeExpression(String name, Expression var) { super(name); this.var = var; } @Override int interpret(Context ctx) { return -var.interpret(ctx); } }
定义一个运算环境,用于给变量赋值
class Context { Mapmap = new HashMap (); void assign(Expression var, int value) { map.put(var, value); } int lookup(Expression var) { Object obj = map.get(var); if(null == obj) { // 如果变量未初始化,默认是0 return 0; } return (Integer) obj; } }
客户端调用:
public static void main(String[] args) { Context ctx = new Context(); Variable a = new Variable("a"); Variable b = new Variable("b"); Variable c = new Variable("c"); // 不初始化,默认为0 ctx.assign(a, 1); ctx.assign(b, 2); System.out.println("a = " + a.interpret(ctx)); System.out.println("b = " + b.interpret(ctx)); System.out.println("c = " + c.interpret(ctx)); // 相反数运算 OppositeExpression opposite = new OppositeExpression("-", a); int rs = opposite.interpret(ctx); String exp = String.format("%s%s = %d", opposite.name, a.name, rs); System.out.println(exp); // 加运算 AddExpression add = new AddExpression(a, "+", b); rs = add.interpret(ctx); exp = String.format("%s %s %s = %d", a.name, add.name, b.name, rs); System.out.println(exp); }
结果:
a = 1
b = 2
c = 0
-a = -1
a + b = 3
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/64006.html
摘要:本文只是寻找设计模式在中的应用。来补全这一块工厂模式中的应用包线程池解释和代码线程池中有线程创建工厂。状态模式中的应用解释和代码根据一个指针的状态而改变自己的行为适配器模式中的应用解释和代码将一个类的接口转换成客户希望的另外一个接口。 前言 最近重学设计模式,而且还有很多源码要看。所以就想一举两得。从源码中寻找设计模式。顺便还可以看看源码。。。本文只是寻找设计模式在java中的应用。优...
摘要:近日,加州大学洛杉矶分校的朱松纯教授等人发布了一篇使用决策树对的表征和预测进行解释的论文。在此论文中,朱松纯等研究者提出了一种新任务,也就是使用决策树在语义层次上来量化解释预测的逻辑。 近日,加州大学洛杉矶分校的朱松纯教授等人发布了一篇使用决策树对 CNN 的表征和预测进行解释的论文。该论文借助决策树在语义层面上解释 CNN 做出的每一个特定预测,即哪个卷积核(或物体部位)被用于预测最终的类...
摘要:解决方案解释器模式来解决用来解决上述问题的一个合理的解决方案,就是使用解释器模式。使用解释器模式重写示例通过上面的讲述可以看出,要使用解释器模式,一个重要的前提就是要定义一套语法规则,也称为文法。#1 场景问题# ##1.1 读取配置文件## 考虑这样一个实际的应用,维护系统自定义的配置文件。 几乎每个实际的应用系统都有与应用自身相关的配置文件,这个配置文件是由开发人员根据需要自定义的,系统...
摘要:设计模式的类别设计模式一共分为种类型,共种。属于结构型的设计模式适配器模式桥接模式装饰模式组合模式外观模式享元模式代理模式。问题描述了应该在何时使用设计模式。解决方案描述了设计的组成成分,它们之间的相互关系及各自的职责和协作方式。 设计模式概述 1. 设计模式是什么 我们在平时编写代码的过程中,会遇到各种各样的问题,细想一下很多问题的解决思路大致一样的,这时候你就可以把解决问题的思路整...
摘要:里氏代换原则里氏代换原则面向对象设计的基本原则之一。里氏代换原则中说,任何基类可以出现的地方,子类一定可以出现。里氏代换原则是对开闭原则的补充。而基类与子类的继承关系就是抽象化的具体实现,所以里氏代换原则是对实现抽象化的具体步骤的规范。 一、设计模式的六大原则: 1、开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修改关闭。在程序需要进行拓展的时候,不...
阅读 1766·2021-10-11 10:59
阅读 2405·2021-09-30 09:53
阅读 1767·2021-09-22 15:28
阅读 2798·2019-08-29 15:29
阅读 1561·2019-08-29 13:53
阅读 3209·2019-08-29 12:34
阅读 2852·2019-08-26 10:16
阅读 2662·2019-08-23 15:16