**请注意!请注意!!!**今天讲给大家讲解非常“有用”的设计模式,解释器模式!!!
设计模式有三大种类,一种是创建型模式,一种是结构型模式,最后一种是行为性模式,那么解释器模式属于哪一种呢?带领大家一起来了解学习解释器模式!
本次介绍围绕着以下五点展开。什么是解释器模式?用来做什么?怎么做?有哪些优点?有哪些不足?
解释器模式顾名思义,就是用来定义和解释。
给定一种特定语言,这个语言有特定的文法,解释器可以解释这个语言中的句子含义。即解释器提供一种语言,如java,同时它也提供一种手段去解析java语言写出来的代码。
大家可能也会想到这就是类似编译原理,一个算术表达式要经过词法分析,语法分析,构建语法树啥的;还有正则表达式;SQL解析,编译器等等,其实都是解析式模式的一种实现。
那怎么做?一个是说要有像编译原理中的终结符和非终结符,构建一颗语法树。同时需要有一个环境类,来管理输入和输出。
这里我们举一个例子,输入一个表达式a+b-c+d-e,同时给这5个变量赋值,计算出它的值。那么使用解释器模式要如何实现?
我们为解释器定义一个抽象解释类Expression,所有的流转通过interpreter方法实现。
上下文管理输入输出使用一个HashMap
去实现。
定义符号解释类SymbolExpression
,加法解释类AddExpreesion
,减法解释类SubExpression
。
类图:
具体代码实现:
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
public abstract class Expression { // map中携带了表达式中的变量名(key) 和 对应的值(value) public abstract int interpreter(Map<String, Integer> var); } public class VarExpression extends Expression { // 表达式中对应的变量名 String key; public VarExpression(String var) { this .key = var; } @Override public int interpreter(Map<String, Integer> var) { return var.get(key); } } public class SymbolExpression extends Expression { // +或-符号 左右两边的表达式 Expression var1; Expression var2; public SymbolExpression(Expression var1, Expression var2) { this .var1 = var1; this .var2 = var2; } @Override public int interpreter(Map<String, Integer> var) { // 实现抽象方法 // 该类不需要用到该方法 默认返回0 return 0 ; } } public class AddExpression extends SymbolExpression { public AddExpression(Expression var1, Expression var2) { super (var1, var2); } @Override public int interpreter(Map<String, Integer> var) { return var1.interpreter(var) + var2.interpreter(var); } } public class SubExpression extends SymbolExpression { public SubExpression(Expression var1, Expression var2) { super (var1, var2); } @Override public int interpreter(Map<String, Integer> var) { return var1.interpreter(var) - var2.interpreter(var); } } public class Calculator { // 表达式 private Expression expression; // 解析出表达式 public Calculator(String expStr) { Stack<Expression> stack = new Stack<>(); Expression left, right = null ; char [] expStrCharArray = expStr.toCharArray(); for ( int i = 0 ; i < expStrCharArray.length; i++) { switch (expStrCharArray[i]) { case '+' : // 加法运算 获取左边表达式 右边数值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push( new AddExpression(left, right)); break ; case '-' : // 减法运算 获取左边表达式 右边数值 left = stack.pop(); right = new VarExpression(String.valueOf(expStrCharArray[++i])); stack.push( new SubExpression(left, right)); break ; default : // 表达式中的变量 stack.push( new VarExpression(String.valueOf(expStrCharArray[i]))); break ; } } // 最后会获得被Expression包装起来的一个表达式 this .expression = stack.pop(); } // 计算结果 public int run(Map<String, Integer> var) { return this .expression.interpreter(var); } } public class Client { public static void main(String[] args) throws IOException { String expStr = getExpStr(); Map<String, Integer> var = getValue(expStr); Calculator calculator = new Calculator(expStr); System.out.println( "运算结果:" + expStr + "=" + calculator.run(var)); } //获得表达式 public static String getExpStr() { return "a+b-c+d-e" ; } //获得值映射 public static HashMap<String, Integer> getValue(String expStr) throws IOException { HashMap<String, Integer> map = new HashMap<>(); for ( char ch : expStr.toCharArray()) { if (ch != '+' && ch != '-' ) { if (! map.containsKey(String.valueOf(ch))) { System.out.print( "请输入" + String.valueOf(ch) + "的值:" ); String in = ( new BufferedReader( new InputStreamReader(System.in))).readLine(); map.put(String.valueOf(ch), Integer.valueOf(in)); } } } return map; } } |
结果
/*
请输入a的值:1
请输入b的值:3
请输入c的值:5
请输入d的值:7
请输入e的值:9
运算结果:a+b-c+d-e=-3
*/
或许看代码会有点云里雾里,希望大家能手动敲一遍,或许会对整个过程有更进一步的理解,在编码的同时不断思考,提升自我。
很容易发现解释器模式是属于行为性模式的一种,这种模式更关注对象之间的通信。
解释器模式优点,结构清晰,可拓展性好。但也有缺点,一般用在比较底层场景,平常敲代码可使用的场景比较少,并且解释器模式采用的是递归的方式,当语言比较长,性能不高;同时如果文法比较复杂,也需要更多的相应解释类。
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!
原文链接:https://blog.csdn.net/KnightHONG/article/details/120693753