概念

  • 给分析对象定义一个语言,并定义该语言的文法表示,再设计一个解析器来解释语言中的句子。也就是说,用编译语言的方式来分析应用中的实例。这种模式实现了文法表达式处理的接口,该接口解释一个特定的上下文。类行为型模式
  • image.png

主要角色

  • 抽象表达式(Abstract Expression)角色:
    • 定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  • 终结符表达式(Terminal Expression)角色:
    • 是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结符表达式(Nonterminal Expression)角色:
    • 也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  • 环境(Context)角色:
    • 通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。
  • 客户端(Client):

    • 主要任务是将需要分析的句子或表达式转换成使用解释器对象描述的抽象语法树,然后调用解释器的解释方法,当然也可以通过环境角色间接访问解释器的解释方法。 ```java /**

      • 抽象表达式(Abstract Expression)角色: */ public abstract class IDCardExpression {

      /**

      • 定义解析逻辑
      • 假设我们需要解析的信息格式为:
      • 上海市:张文宏-医生
      • 武汉市:雷丰阳-程序员
      • 北京市:宋宋-老人
      • 表达式中,“:”以前的是城市,“-”以后的是职业
      • @param expression
      • @return */ abstract boolean interpret(String expression);

}

  1. ```java
  2. /**
  3. * 非终结符表达式(Nonterminal Expression)角色:
  4. */
  5. public class OrExpression extends IDCardExpression {
  6. //组合两个终结表达式。最终的判断结果是终结表达式判断出来的,这个表达式只是一个桥梁
  7. private IDCardExpression cityExp;
  8. private IDCardExpression typeExp;
  9. public OrExpression(IDCardExpression cityExp, IDCardExpression typeExp) {
  10. this.cityExp = cityExp;
  11. this.typeExp = typeExp;
  12. }
  13. @Override
  14. boolean interpret(String expression) {
  15. //定义所有终结表达式的合并逻辑
  16. return cityExp.interpret(expression) || typeExp.interpret(expression);
  17. }
  18. }
/**
 * 终结符表达式(Terminal Expression)角色
 */
public class TerminalExpression extends IDCardExpression {

    IDCardExpression childExp;

    Set<String> data;  //免费数据
    String symbol; //定义解析用的符号如  : -

    public TerminalExpression( Set<String>  data,String symbol){
        this.data = data;
        this.symbol = symbol;
    }

    @Override
    boolean interpret(String expression) {
        //上海市:张文宏-医生
        //1、先按照指定符号分割
        String[] split = expression.split(symbol);

        // 冒号:  上海市              张文宏-医生
        // 短横线  上海市:张文宏       医生
        boolean result = false;
        for (String s : split) {
            if(data.contains(s)){
                return true;
            };//说明是免费的信息里面的
        }

        //可以继续子解析
//        childExp.interpret(expression);

        //不在免费行列
        return false;
    }
}
/**
 * 环境(Context)角色:
 */
public class Area {
    Set<String> city = new HashSet<>();


    Set<String> type = new HashSet<>();
    IDCardExpression idCardReader;//读卡器,表达式解析器

    //环境类持有表达式

    public Area(){
//        {"武汉市","上海市"};//免费城市
//        {"医生","老人","儿童"};//免费人群
        city.add("武汉市");
        city.add("上海市");

        type.add("医生");
//        type.add("老人");
        type.add("儿童");
        //最小解析
        TerminalExpression city =
                new TerminalExpression(this.city, ":");
        //最小解析
        TerminalExpression type =
                new TerminalExpression(this.type, "-");


        //以上满足一个即可
        idCardReader = new OrExpression(city,type);

    }

    /**
     * 传入表达式,判断当前表达式是否指定为免费人群
     * @param expression
     */
    void getTicket(String expression){
        boolean interpret = idCardReader.interpret(expression);
        if(interpret){
            System.out.println("恭喜你,免票通过....");
        }else {
            System.out.println("对不起,请2元购票....");
        }
    }
}
/**
 * 客户端(Client):
 */
public class MainTest {

    public static void main(String[] args) {

        Area area = new Area();
        /**
         *  上海市:张文宏-医生
         *  武汉市:雷丰阳-程序员
         *  北京市:宋宋-老人
         */
        String sr = "武汉市:雷丰阳-程序员";

        area.getTicket(sr);

    }
}

应用场景

  • Spring的表达式解析:#{}
  • Thymeleaf等模板引擎的语法解析
  • 编译原理