设计模式源码git地址:design-pattern-src: 设计模式源码 (gitee.com)

  1. 定义
  2. 用的原因
  3. 缺点
  4. 角色
  5. 场景举例

定义

用编译语言的方式来分析应用中的实例

为什么要用

扩展性好,利用继承机制扩展文法

缺点

效率低,调用麻烦,容易引起类膨胀,这个模式很少能用到

角色

抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。

终结符表达式(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。

非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。

上下文(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

场景举例

设计一个读卡器,北京或太原的老年和孕妇刷卡免费,其余人群标准价

首先设计文法

1
2
3
<expression> ::= <city>的<person>
<city> ::= 北京|太原
<person> ::= 老人|孕妇

uml类图

img

程序调用

1
2
3
4
5
6
7
8
//创建上下文运行环境,这里指刷卡用的bus
Context bus = new Context();
//不同人群刷卡
System.out.println("公交乘车开始刷卡");
bus.freeRide("北京的老人");
bus.freeRide("太原的孕妇");
bus.freeRide("太原的儿童");
bus.freeRide("上海的老人");

输出

1
2
3
4
5
公交乘车开始刷卡
哔!老人卡,欢迎乘车,您本次乘车免费!
哔!孕妇卡,欢迎乘车,您本次乘车免费!
哔!欢迎乘车,您本次乘车扣费2元!
哔!欢迎乘车,您本次乘车扣费2元!

抽象表达式

1
2
3
public interface Expression {
boolean interpret(String info);
}

终结符表达式(具体实现者)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class TerminalExpression implements Expression{
private Set<String> set = new HashSet<String>();
public TerminalExpression(String[] data) {
for (int i = 0; i < data.length; i++) {
set.add(data[i]);
}
}
public boolean interpret(String info) {
if (set.contains(info)) {
return true;
}
return false;
}
}

非终结符表达式(具体实现者)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class AndExpression implements Expression{
//左半部分
private Expression left;
//右半部分
private Expression right;
//切分关键字
public static final String FLEX = "的";
public AndExpression(Expression city, Expression person) {
this.left = city;
this.right = person;
}
public boolean interpret(String info) {
String s[] = info.split(FLEX);
//符合文法的全部才会返回true
return left.interpret(s[0]) && right.interpret(s[1]);
}
}

上下文Context

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Context {
private String[] citys = {"北京", "太原"};
private String[] persons = {"老人", "孕妇"};
private Expression expression;
public Context() {
Expression city = new TerminalExpression(citys);
Expression person = new TerminalExpression(persons);
expression = new AndExpression(city, person);
}
public void freeRide(String info) {
//提示语,可自行设置
String s1 = "哔!"+info.split(FLEX)[1] + "卡,欢迎乘车,您本次乘车免费!";
String s2 = "哔!欢迎乘车,您本次乘车扣费2元!";
System.out.println(expression.interpret(info) ? s1 : s2);
}
}