学习设计模式之解释器模式

解释器模式
定义一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

类结构图
在这里插入图片描述
Context
包含解释之外的一些全局信息。
AbstractExpression
声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
TerminalExpression
终结符表达式,实现与文法中的终结符相关联的解释操作。
NonterminalExpression
非终结符表达式,为文法中的非终结符实现解释操作。

代码示例
乐谱大家都见过,那么我们来自定义一下 O 表示音阶、C D E F G A B 表示 Do-Re-Mi-Fa-So-La-Ti。

public class Context {
    private String playText;

    public String getPlayText() {
        return playText;
    }

    public void setPlayText(String playText) {
        this.playText = playText;
    }
}

public abstract class Expression {
    abstract void excute(String key, String value);

    public void interpret(Context context) {
        if (null == context.getPlayText() || "".equals(context.getPlayText())) {
            return;
        }
        // 解析的字符串例如 O 3 E 0.5
        String playKey = context.getPlayText().substring(0, 1);
        context.setPlayText(context.getPlayText().substring(2));
        String value = context.getPlayText().substring(0, context.getPlayText().indexOf(" "));
        context.setPlayText(context.getPlayText().substring(context.getPlayText().indexOf(" ") + 1));
        excute(playKey, value);
    }
}

public class Note extends Expression {
    @Override
    void excute(String key, String value) {
        String note = "";
        switch (key) {
            case "C":
                note = "1";
                break;
            case "D":
                note = "2";
                break;
            case "E":
                note = "3";
                break;
            case "F":
                note = "4";
                break;
            case "G":
                note = "5";
                break;
            case "A":
                note = "6";
                break;
            case "B":
                note = "7";
                break;
        }
        System.out.print(note + "\t");
    }
}

public class Scale extends Expression {
    @Override
    void excute(String key, String value) {
        String scale = "";
        switch (Integer.parseInt(value)) {
            case 1:
                scale = "低音";
                break;
            case 2:
                scale = "中音";
                break;
            case 3:
                scale = "高音";
                break;
        }
        System.out.print(scale + "\t");
    }
}

客户端示例

public class ExpressionClient {
    public static void main(String[] args) {
        Context context = new Context();
        context.setPlayText(
                "O 2 E null G null A 3 E null G null D 3 E null G null A null O 3 C 1 O 2 A null G 1 C null E null E 3 ");
        Expression expression = null;
        while (context.getPlayText().length() > 0) {
            String str = context.getPlayText().substring(0, 1);
            switch (str) {
                case "O":
                    expression = new Scale();
                    break;
                case "C":
                case "D":
                case "E":
                case "F":
                case "G":
                case "A":
                case "B":
                case "P":
                    expression = new Note();
                    break;
            }
            expression.interpret(context);
        }
    }
}

运行结果

中音	3	5	6	3	5	2	3	5	6	高音	1	中音	6	5	1	3	3	
Process finished with exit code 0

优点
可以比较方便的修改和扩展语法规则。

缺点
几乎针对每一个规则都定义了一个类,所以如果一个语法的规则比较多,那对于语法的维护工作也会变得非常困难。

猜你喜欢

转载自blog.csdn.net/qq_16830879/article/details/88695228