X.d 笔记

小Web,大世界

0%

设计模式(15):解释器模式 Interpreter

解释器嘛,就是个翻译,比如有道词典什么的,哈哈。

解释器模式 Interpreter

题义:给定一个语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。解释器模式将描述怎样在有了一个简单的文法后,使用模式设计解释这些语句。在解释器模式里面提到的语言是指任何解释器对象能够解释的任何组合。在解释器模式中需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则。每一个命令对象都有一个解释方法,代表对命令对象的解释。命令对象的等级结构中的对象的任何排列组合都是一个语言。

问题:

A class of problems occurs repeatedly in a well-defined and well-understood domain. If the domain were characterized with a “language”, then problems could be easily solved with an interpretation “engine”.

意图:

  • Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.
  • Map a domain to a language, the language to a grammar, and the grammar to a hierarchical object-oriented design.

代码

例:像翻译软件什么的都像是解释器,你看不懂外语,复制过去让软件翻译一下,就可以了。搜索引擎也是解释器,你输入的词要联想你想要找的东西。太高端了搞不了,这里我用解释器实现一个相当相当简单的计算器,看下代码即可

代码一:用户输入

/**
 * @author xdnote.com
 * 用户输入,可以输入一个简单的算术字符串 如 “1+2” “3*4”等
 * */
public class Input {

    private static final Pattern ptn = Pattern.compile("(\\d+)([\\+\\-\\*/])(\\d+)");

    private boolean validate = false;

    private int x;

    private int y;

    private String operation;

    public Input(String str) {
        this.interpret(str);
    }

    private void interpret(String str){
        Matcher m = ptn.matcher(str);
        if(m.find()){
            this.x = Integer.parseInt(m.group(1));
            this.y = Integer.parseInt(m.group(3));
            this.operation = m.group(2);
            this.validate = true;
        }else{
            this.validate = false;
        }
    }

    public boolean isValidate() {
        return validate;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public String getOperation() {
        return operation;
    }
}

代码二:解释器

public class Interpreter {

    private String local = "zh-cn";

    public Interpreter(String local) {
        if(local.equals("en")){
            this.local = local;
        }
    }

    public  void exec(String str){
        write(read(new Input(str)));
    }

    private Output read(Input input){
        return new Output(input);
    }

    private void write(Output out){
        System.out.println(out.getResult(local));
    }
}

代码三:解释器的输出,支持中英文

public class Output {

    private final String[] zn_cn=new String[]{"零","一","二","三","四","五","六","七","八","九","加上","减去","乘以","除以","等于","输入有误"};
    private final String[] en=new String[]{"zero ","one ","two ","three ","four ","five ","six ","seven ","eight ","night ","add ","subtract ","ride ","divide ","is ","Input Error"};

    private Input input;

    public Output(Input input) {
        this.input = input;
    }

    private String getTran(int x,String[] trans){
        String value = String.valueOf(x);
        StringBuffer sb = new StringBuffer();
        for(int i=0,j=value.length();i<j;i++){
            int index =value.charAt(i)-48;
            sb.append(trans[index]);
        }
        return sb.toString();
    }

    public String getResult(String local){
        String[] trans =  local.equalsIgnoreCase("en")?en:zn_cn;
        if(!this.input.isValidate()){
            return trans[15];
        }else{
            StringBuffer sb = new StringBuffer();
            int x = input.getX();
            int y = input.getY();
            String operation = input.getOperation();
            int result=0;
            sb.append(this.getTran(x, trans));
            if(operation.equals("+")){
                sb.append(trans[10]);
                result = x+y;
            }else if(operation.equals("-")){
                sb.append(trans[11]);
                result = x-y;
            }else if(operation.equals("*")){
                sb.append(trans[12]);
                result = x*y;
            }else if(operation.equals("/")){
                sb.append(trans[13]);
                result = x/y;
            }
            sb.append(this.getTran(y, trans));
            sb.append(trans[14]);
            sb.append(this.getTran(result, trans));
            return sb.toString();
        }
    }

}

代码四:客户端使用

/**
 * @author xdnote.com
 * 解释器模式. 比如输入"@"即代表后面的一串为address,在office里面输入"2+4"放开后也会出现6 
 * */
public class Client {

    public static void main(String[] args){
        Interpreter zh = new Interpreter("zh-cn");
        zh.exec("3+5");
        zh.exec("4*2");
        zh.exec("无聊死了");

        Interpreter en = new Interpreter("en");
        en.exec("3+5");
        en.exec("4*2");
        en.exec("dsfaasdfa");
    }
}

小结

解释器模式 Interpreter
这模式个人很少用,所以上面的代码是有问题的,解释器只能解释,不能计算。所以计算应该另外写在一个类里面。

  • 使用频率:极低
    感觉没什么用,就不说了。有各种工厂策略代理桥接什么的,不知道什么场景能使用。如果说正则表达式提取出内容再重现也算的话就应该较多了,但这样就谈不上模式了~

  • 利弊影响:极低
    个人没用过。