解释器模式是一种行为型设计模式,它可以用来定义和解释一种语言的文法,并根据文法对句子进行解释。解释器模式通常用于编译器,表达式计算,正则表达式,机器人等领域。
它的基本思想是为每个符号(终结符或非终结符)创建一个类,然后使用这些类来构建抽象语法树。
在Java中,解释器模式的实现可以参考以下步骤:
1. 定义一个抽象表达式接口(AbstractExpression),声明一个抽象的解释方法,参数是一个上下文对象(Context)。
2. 定义一个终结符表达式类(TerminalExpression),实现抽象表达式接口,表示语言中的基本元素。
3. 定义一个非终结符表达式类(NonterminalExpression),实现抽象表达式接口,表示语言中的复合元素。
4. 定义一个上下文类(Context),封装一些全局信息,如变量映射等。
5. 定义一个客户端类(Client),构建一个抽象语法树,调用抽象表达式的解释方法得到结果。
下面是一个简单的Java程序,使用解释器模式来实现一个简单的算术表达式求值:
在这段代码中,定义了一个**表达式接口**,它有一个interpret()方法,用于返回表达式的值。然后定义了五个实现了表达式接口的类:Number、Add、Subtract、Multiply和Divide,分别表示数字、加法、减法、乘法和除法。每个类都有自己的构造方法和interpret()方法的实现。
最后,在测试类中,创建了一些复合表达式对象,并调用它们的interpret()方法来计算表达式的值。
// 定义一个抽象表达式接口
interface Expression {
int interpret();
}
// 定义一个数字类,实现表达式接口
class Number implements Expression {
private int value;
public Number(int value) {
this.value = value;
}
@Override
public int interpret() {
return value;
}
}
// 定义一个加法类,实现表达式接口
class Add implements Expression {
private Expression left;
private Expression right;
public Add(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() + right.interpret();
}
}
// 定义一个减法类,实现表达式接口
class Subtract implements Expression {
private Expression left;
private Expression right;
public Subtract(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() - right.interpret();
}
}
// 定义一个乘法类,实现表达式接口
class Multiply implements Expression {
private Expression left;
private Expression right;
public Multiply(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret() * right.interpret();
}
}
// 定义一个除法类,实现表达式接口
class Divide implements Expression {
private Expression left;
private Expression right;
public Divide(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret() throws ArithmeticException{
if (right.interpret() ==0){
throw new ArithmeticException("除数不能为零");
}
return left.interpret() /right.interpret();
}
}
// 定义一个测试类,创建并解释一些简单的算术表达式
public class InterpreterTest {
public static void main(String[] args) {
// 创建一些数字对象
Number one = new Number(1);
Number two = new Number(2);
Number three = new Number(3);
Number four = new Number(4);
// 创建一些复合表达式对象
Add add1 = new Add(one,two); // 表示1+2
Subtract sub1= new Subtract(three,four); // 表示3-4
Multiply mul1= new Multiply(add1,sub1); // 表示(1+2)*(3-4)
Divide div1= new Divide(mul1,two); // 表示((1+2)*(3-4))/2
// 调用interpret方法求值
System.out.println(div1.interpret()); // 输出-3
}
}
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl
如thisquestion,当在其自己的赋值中使用未定义的局部变量时,它的计算结果为nil。x=x#=>nil但是当局部变量的名称与现有的方法名称冲突时,就比较棘手了。为什么下面的最后一个示例返回nil?{}.instance_eval{a=keys}#=>[]{}.instance_eval{keys=self.keys}#=>[]{}.instance_eval{keys=keys}#=>nil 最佳答案 在Ruby中,因为可以在没有显式接收器和括号的情况下调用方法,所以在局部变量引用和无接收器无参数方法调用之间存在语法歧义:f
我使用Jekyll运行博客,并认为我会解决RedcarpetMarkdown解释器,因为它是developedandusedbyGitHub.好吧,我只是碰巧遇到了一个错误,去检查问题,然后foundthis.Maintainersays,"Asyouprobablyhavenoticed(harharharhar)Idon'thavetimetomaintainRedcarpetanymore.It'snotapriorityforme(IfindMarkdownthoroughlyboring)andit'snotapriorityforGitHub,becausewenolong
我经常迷上ruby的一件事是递归模式。例如,假设我有一个数组,它可能包含无限深度的数组作为元素。所以,例如:my_array=[1,[2,3,[4,5,[6,7]]]]我想创建一个方法,可以将数组展平为[1,2,3,4,5,6,7]。我知道.flatten可以完成这项工作,但这个问题是作为我经常遇到的递归问题的一个例子-因此我试图找到一个更可重用的解决方案。简而言之-我猜这种事情有一个标准模式,但我想不出任何特别优雅的东西。任何想法表示赞赏 最佳答案 递归是一种方法,它不依赖于语言。您在编写算法时要考虑两种情况:再次调用函数的情
这应该是一个简单的问题,但我找不到任何相关信息。给定一个Ruby中的正则表达式,对于每个匹配项,我需要检索匹配的模式$1、$2,但我还需要匹配位置。我知道=~运算符为我提供了第一个匹配项的位置,而string.scan(/regex/)为我提供了所有匹配模式。如果可能,我需要在同一步骤中获得两个结果。 最佳答案 MatchDatastring.scan(regex)do$1#Patternatfirstposition$2#Patternatsecondposition$~.offset(1)#Startingandendingpo