解释器模式(Interpreter Pattern): 给定一个语言, 定义它的文法的一种表示, 并定义一个解释器, 这个解析器使用该来解释语言中的句子.
设计模式-概述
解析器模式使用频率较低, 它描述了如何使用面向对象语言构成一个语言解析器.
结构
解析器模式包含4个角色:
- 抽象表达式(AbstractExpression): 所有终结符表达式和非终结符表达式的公共父类.
- 终结符表达式(TerminalExpression): 抽象表达式的子类, 实现了文法中的终结符相关解析操作, 每一个终结符对应一个该类的实例.
- 非终结符表达式(NonterminalExpression): 抽象表达式的子类, 实现了文法中非终结符的解释操作, 非终结符表达式包含了其他终结符表达式和非终结符表达式, 因此通常使用递归来实现.
- 环境类(Context): 存储了解析器的上下文, 包含需要解析的语句.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| @@startuml interpreter-1 !include common.cuml
Class(Context,"环境类") { }
Class(AbstractExpression,"抽象表达式") { + interpret(Context ctx) : void }
Class(TerminalExpression,"终结符表达式") { + interpret(Context ctx) : void }
Class(NonterminalExpression,"非终结符表达式") { + interpret(Context ctx) : void }
Class(Client,"客户端") { }
Client .right.> AbstractExpression Client .right.> Context AbstractExpression ..> Context TerminalExpression -up-|> AbstractExpression NonterminalExpression -up-|> AbstractExpression NonterminalExpression o--> AbstractExpression
@@enduml
|
代码实现
- 定义TerminalExpression输出A, NonterminalExpression输出其内部包含的左右内容中间
-
分割.
- 使用Context定义好规则.
- 实例化一个NonterminalExpression对象.
- 调用其
interpret
方法, 返回结果.
非终结符表达式 和 终结符表达式 可以有多种不同实现, 以应对不同的语法结构.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| package com.yuda.desigmode.main4;
import java.util.HashMap;
public class Main4 { public static void main(String[] args) { Context context = new Context(); context.assign("TerminalExpression", "A"); context.assign("NonterminalExpression", "B"); AbstractExpression TerminalExpressionA = new TerminalExpression(); AbstractExpression TerminalExpressionB = new TerminalExpression(); AbstractExpression NonterminalExpression = new NonterminalExpression(TerminalExpressionA, TerminalExpressionB); System.out.println("结果为:" + NonterminalExpression.interpret(context)); } }
class Context { private HashMap<String, String> map = new HashMap<>();
public void assign(String key, String value) { map.put(key, value); }
public String lookup(String key) { return map.get(key); } }
abstract class AbstractExpression { public abstract String interpret(Context context); }
class TerminalExpression extends AbstractExpression {
@Override public String interpret(Context context) {
System.out.printf("TerminalExpression输出: %s\n", context.lookup(this.getClass().getSimpleName())); return context.lookup(this.getClass().getSimpleName()); } }
class NonterminalExpression extends AbstractExpression {
private AbstractExpression left; private AbstractExpression right;
public NonterminalExpression(AbstractExpression left, AbstractExpression right) { this.left = left; this.right = right; }
@Override public String interpret(Context context) {
String interpret = left.interpret(context); System.out.printf("NonterminalExpression: %s\n", context.lookup(this.getClass().getSimpleName())); String interpret1 = right.interpret(context); System.out.printf("NonterminalExpression: %s\n", context.lookup(this.getClass().getSimpleName())); return interpret + "-" + interpret1; } }
|
结果输出:
1 2 3 4 5
| TerminalExpression输出: A NonterminalExpression: B TerminalExpression输出: A NonterminalExpression: B 结果为:A-A
|
使用场景
- 当语言的文法较为简单, 且执行效率不是关键问题时.
- 当问题重复出现, 且可以用一种简单的语言来进行表达时.
- 当一个语言需要解释执行, 并且语言中的句子可以表示为一个抽象语法树的时候.
具体应用
XML的文档解释: 基于DOM的XML分析器将一个XML文档转换成一个对象模型的集合.