一、模式介绍
解释器模式,定义一个解释器,用来解释“特定的文法表示”,通常是计算或运行出结果。
如果某类有共性问题频繁发生,如:有三个变量假设未a、b、c,需求经常需要计算和或差,如a+b+c/a-b+c/
a+b-c/a-b-c,等等它们的种类可能会很多且不可预知(可能由输入决定),观察发现他们他们的共性在于:有两种元素:运算逻辑(+/-)和参数单元(a/b/c/其它),运算逻辑依赖左右两个参数单元可运算出结果,参数单元没有其它依赖,于此,可抽象出两类表达式,一类是运算表达式,一类是参数表达式,由于运算符合和参数单元需要动态确定,故需要剥离其实质进一步抽象,统一为:表达式。
解释器模式的应用,首先必须要定义“文法基础”,即“表达式语法”,然后按照此语法写出的文法语句,可以通过解析得到一系列可执行的接口指令,最终,指令按照预先的文法输入执行,以满足一类业务需求。
通常解释器模式的实施,会不可避免的涉及两类表达式:终结表达式、非终结表达式。终结表达式是指令执行的基础单元(如变量),非终结表达式则是基于终结表达式进行可配置的业务流程(如运算符)。
二、原理图
三、示例代码
import java.util.*;
class Calculator {
Expression expression;
Context context;
void initAlg(String alg) {
// Stack stack = new Stack();//线程安全
Deque<Expression> stack = new ArrayDeque<Expression>();//官方建议的Stack替代用法
char[] s = alg.toCharArray();
for (int i = 0; i < s.length; i++) {
char c = s[i];
switch (c) {
case '+':
stack.push(new PlusExpression(stack.pop(), new VariableExpression(s[++i])));
break;
case '-':
stack.push(new MinusExpression(stack.pop(), new VariableExpression(s[++i])));
break;
default:
stack.push(new VariableExpression(c));
}
}
expression = stack.pop();
}
int run(final Map<Character, Integer> values) {
return expression.explain(new Context() {
@Override
public int getValue(char key) {
return values.get(key);
}
});
}
}
interface Context {
int getValue(char key);
}
interface Expression {
int explain(Context context);
}
abstract class CalculateExpression implements Expression {
Expression left;
Expression right;
public CalculateExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
}
class PlusExpression extends CalculateExpression {
public PlusExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int explain(Context context) {
return left.explain(context) + right.explain(context);
}
}
class MinusExpression extends CalculateExpression {
public MinusExpression(Expression left, Expression right) {
super(left, right);
}
@Override
public int explain(Context context) {
return left.explain(context) - right.explain(context);
}
}
class VariableExpression implements Expression {
char key;
public VariableExpression(char key) {
this.key = key;
}
@Override
public int explain(Context context) {
return context.getValue(key);
}
}
public class T {
public static void main(String[] args) {
Calculator calculator = new Calculator();
String alg = "a+b-c+d";
calculator.initAlg(alg);
Map<Character, Integer> valueMap = new HashMap<Character, Integer>();
valueMap.put('a', 1);
valueMap.put('b', 2);
valueMap.put('c', 3);
valueMap.put('d', 5);
int result = calculator.run(valueMap);
System.out.println("表达式:" + alg);
System.out.println("变量值:" + valueMap);
System.out.println("计算结果:" + result);
}
}
输出:
表达式:a+b-c+d
变量值:{d=5, b=2, c=3, a=1}
计算结果:5
另一个示例:
package test;
import java.util.*;
/**
* 文法模版定义:(((str1)sub3(str2)repeat2)reverse,str3)add
* sub3:表示截取前3个
* repeat2:表示重复两遍
* reverse:反转字符串
* add: 拼接 字符串
* 本示例,省去了解析“模版”得到“解释器”的过程,直接手动new *Expression(*)建立
*/
class Context {
Map<Object, String> values = new HashMap<Object, String>();
void addResult(Object key, String result) {
values.put(key, result);
}
String getResult(Object key) {
return values.get(key);
}
}
interface Expression {
String explain(Context context);
}
class SubExpression implements Expression {
Expression target;
int count;
public SubExpression(int count, Expression target) {
this.count = count;
this.target = target;
}
@Override
public String explain(Context context) {
String result = target.explain(context);
return result.substring(0, count);
}
}
class RepeatExpression implements Expression {
Expression target;
int count;
public RepeatExpression(int count, Expression target) {
this.count = count;
this.target = target;
}
@Override
public String explain(Context context) {
String result = target.explain(context);
StringBuilder stringBuilder = new StringBuilder(result);
for (int i = 0; i < count; i++) {
stringBuilder.append(result);
}
return stringBuilder.toString();
}
}
class ReverseExpression implements Expression {
Expression target;
public ReverseExpression(Expression target) {
this.target = target;
}
@Override
public String explain(Context context) {
String result = target.explain(context);
StringBuilder stringBuilder = new StringBuilder(result);
return stringBuilder.reverse().toString();
}
}
class AddExpression implements Expression {
Expression left;
Expression right;
public AddExpression(Expression left, Expression right) {
this.left = left;
this.right = right;
}
@Override
public String explain(Context context) {
return left.explain(context) + right.explain(context);
}
}
class NopExpression implements Expression {
Object key;
public NopExpression(Object key) {
this.key = key;
}
@Override
public String explain(Context context) {
return context.getResult(key);
}
}
public class Main {
public static void main(String[] args) {
Object o1 = "a";
Object o2 = "b";
Context context = new Context();
context.addResult(o1, "abcde");
context.addResult(o2, "new");
Expression e = new AddExpression( // 4.将3得到的字符串+o2
new ReverseExpression( // 3.将2得到的字符串反转
new RepeatExpression(1, // 2.将1得到的字符串重复一遍
new SubExpression(3, // 1.截取o1的前三个
new NopExpression(o1)))),
new NopExpression(o2));
System.out.println(e.explain(context));
}
}
其实,解释器模式主要在于能够 定义出“文法格式”,并且能够解析后通过表达式来执行!
http://www.cnblogs.com/cbf4life/archive/2009/12/17/1626125.html