解释器模式
Interpreter Pattern:解释器模式,是GoF23种设计模式中属于行为型模式的一种。
解释器模式是用于:定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
嗯,通俗点说就是,给出一个解释语句的规则,然后用这个规则去解释语句。
比如说:规定句子的组成为主语+谓语+宾语。那么对于用户给出的任意一句语句,都是用这个规则去解释从而找出语句中的主语,谓语,宾语。
结构
结合类图分析,解释器模式一共有着四个对象:
- 抽象表达式对象(Abstract Expression):声明统一解释的操作或者说是定义规范的接口。
- 终结符表达式对象(Terminal Expression):实现文法中关于终结符的解释操作。
- 非终结符表达式对象(Nonterminal Expression):实现文法中关于非终结符的解释操作。
- 上下文对象(Context):包含一些全局的信息。
举例
- 体现解释器的一种常用的技术就是正则表达式。实际使用中,对于emial,电话号码的判断或者校验都可以使用正则表达式,而使用自己定义的正则表达式去解释字符串的时候,就会用到对于的解释器,在解释器中定义了一个文法或者说规范,如何表示一个特定的正则表达式和怎么去解释这个正则表达式。
- 嗯,更实际一点的就是编译器了,其实各大编译器就是一个超级大型的解释器。
- 对于计算器来说也是一个解释器,解释加减乘除,括号,运算表达式,运算规则等等。
注意
- 解释器模式的使用要求较高,通常使用的场景是当有一个语言需要解释执行的时候,而且可以将语言中的句子表示为一个抽象语法树,就可以使用解释器模式。
- 解释器的使用场景相对来说是比较少的,而且对于比较复杂的文法也会造成类的膨胀和难以维护的缺点。
- 同时解释器模式会采用递归的调用方法,所以性能方面和内存占用方面有所欠缺。
一个小DEMO
-
场景
以计算器的基础实现为例子吧,实现加减乘除的运算。
-
准备上下文对象
/** * 解释器模式——上下文对象 * 嗯 这里也就是计算表达式对象 * @author wq */ public class Context { // 运算表达式 数字和运算符只见使用一个空格分隔 private String operationString; public String getOperationString() { return operationString; } public void setOperationString(String operationString) { this.operationString = operationString; } }
-
解释器
/** * 解释器模式——抽象表达式 * @author wq */ public abstract class AbstractExpression { // 解释器 public void interpret(Context context) { if (context == null || context.getOperationString().length() == 0) { return; } else { String[] strings = context.getOperationString().split(" "); int number1 = Integer.parseInt(strings[0]); String operation = strings[1]; int number2 = Integer.parseInt(strings[2]); // 调用执行的方法 excute(number1, operation, number2); } } public abstract void excute(int number1,String operation,int number2); }
-
实现计算的解释器
/** * 解释器模式——具体表达式对象 * @author wq */ public class Operation extends AbstractExpression{ @Override public void excute(int number1, String operation, int number2) { switch (operation) { case "+": System.out.println(number1 + number2); break; case "-": System.out.println(number1 - number2); break; case "*": System.out.println(number1 * number2); break; case "/": System.out.println(number1 / number2); break; default: System.out.println("不支持"); break; } } }
-
测试类
/** * 解释器模式——测试类 * @author wq */ public class Main { public static void main(String[] args) { Context context = new Context(); context.setOperationString("1 + 2"); Operation operation = new Operation(); System.out.print("计算后的结果为:" + context.getOperationString() + " = "); operation.interpret(context); } }
-
测试走一波
计算后的结果为:1 + 2 = 3