行为型模式之解释器模式(Interpreter)

一、模式介绍

    解释器模式,定义一个解释器,用来解释特定的文法表示”,通常是计算或运行出结果。

    如果某类有共性问题频繁发生,如:有三个变量假设未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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值