设计模式-解释器模式

时间:2022-02-12 14:44:54

直接进入主题,解释器UML图

设计模式-解释器模式

 

 

从UML图可以看出

核心是AbstractExpression类,作为解释器的抽象层他的核心方法是Interpret(Content)

好的,现在我们可以去思考了,怎么写解释器呢?

我一般从这个方面开始思考的

伪代码

step1: 核心方法的入参是Content类,那么我们先创造一个Content类吧。

step2: 写一个接口或者抽象类Expression 抽象方法Interpret(Content)。

step3: 实现抽象类Expression 抽象方法Interpret(Content)。

 

那我们尝试写了一个10以内数字的加法和减法吧

创建一个Content类

public class Content {
    //输入
    private char[] inputs;
    //结果
    private int result=0;

    //指针标记
    private int mark=0;
    
    //数字队列
    private ArrayBlockingQueue<Integer> numQueque = new ArrayBlockingQueue<Integer>(20);
    
    //符号队列
    private ArrayBlockingQueue<Character> optQueque = new ArrayBlockingQueue<Character>(20);
    
    public Content(char[] inputs) {
        this.inputs = inputs;
    }

 

 

这里我用两个队列来分开保存指令(我分为数字指令和操作指令)为了之后的计算器能够方便取值操作

不过这样的话,初始化Content类就不是很方便了,所以我又写了一个GammarParser类来初始化和检测语法。

public class GammarParse {
    
    private String numError="数字错误:";
    private String optError="符号错误:";
    
    public Content parseToContent(String str) throws ParseException, InterruptedException{
        Content content = new Content(str.toCharArray());
        pushConentOptAndNumQueque(content);
        return content;
    }
    
    /**
     * 将输入压入content的Queque
     * @param content
     * @throws ParseException
     * @throws InterruptedException 
     */
    public void pushConentOptAndNumQueque(Content content) throws ParseException, InterruptedException{
        for (char c : content.getInputs()) {
            if(content.getMark()%2==0){//标志位是双数则为数字
            try {
                content.getNumQueque().put(Integer.parseInt(String.valueOf(c)));
            } catch (Exception e) {
                throw new ParseException(numError+c);
            }
            }else {
                grammarCheck(c);
                content.getOptQueque().put(c);
            }
            content.setMark(content.getMark()+1);
        }
    }
    
    /**
     * 符号检查器
     * @param c
     * @throws ParseException
     */
    private void grammarCheck(char c) throws ParseException{
        if(!(c=='+'||c=='-')){
            throw new ParseException(optError+c);
        }
    }
    
}

 

 

 

写一个接口或者抽象类Expression 抽象方法Interpret(Content)。

public interface Interperter {

    void interperter(Content content); 
}

 

实现抽象类Expression 抽象方法Interpret(Content)的类CalcInterperter。

public class CalcInterperter implements Interperter{

    @Override
    public void interperter(Content content) {
        content.setResult(content.getNumQueque().poll());//第一个数字队列直接赋值给result
        while(!content.getNumQueque().isEmpty()){
            switch (content.getOptQueque().poll()) {
            case '+':
                content.setResult(content.getResult()+content.getNumQueque().poll());
                break;
            case '-':
                content.setResult(content.getResult()-content.getNumQueque().poll());
                break;
            default:
                break;
            }
        }
    }

}

 

这里我判断数字队列不为空则将数字出队同时与符号队列出队的元素进行计算。

 

好了,简单的1-10内的加减法计算器做完了。让我们来跑一下单元测试吧

public class Client {
    @Test
    public void test() throws ParseException, InterruptedException{
        List<String> expresses = new ArrayList<String>();
        expresses.add( "1+2");
        expresses.add( "1+2+3");
        expresses.add( "1+2+5");
        expresses.add( "1+2-3");
        expresses.add( "1+2-9");
        expresses.add( "1+2-8+2");
        
        GammarParse paser = new GammarParse();
        CalcInterperter calc = new CalcInterperter();
        for (String exp : expresses) {
            Content content = paser.parseToContent(exp);
            calc.interperter(content);
            System.out.println(exp+" = "+ content.getResult());
        }
    }
}
1+2 = 3
1+2+3 = 6
1+2+5 = 8
1+2-3 = 0
1+2-9 = -6
1+2-8+2 = -3