行为型模式(Behavioral Pattern)是对不同的对象之间划分责任和算法的抽象化;
行为型模式共有11种:
■ 模板方法模式
■ 命令模式
■ 责任链模式
■ 策略模式
■ 迭代器模式
■ 中介者模式
■ 观察者模式
■ 备忘录模式
■ 访问者模式
■ 状态模式
■ 解释器模式
一、解释器模式的简介
■ 给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子;

image.png
解释器5个角色:
■ 抽象表达式(Abstract Expression)角色:
该角色声明一个所有的具体表达式角色都需要实现的抽象接口,该接口主要是一个解释操作interpret()方法;
■ 终结符表达式(Terminal Expression)角色:
该角色实现了抽象表达式角色所要求的接口,文法中的每一个终结符都有一个具体终结表达式与之对应;
■ 非终结符表达式(Nonterminal Expression)角色:
该角色是一个具体角色,文法中的每一条规则都对应一个非终结符表达式类;
■ 环境(Context)角色:
该角色提供解释器之外的一些全局信息;
■ 客户端(Client)角色:
该角色创建一个抽象语法树,调用解释操作;
二、解释器模式的优缺点
解释器模式的优点:
■ 简单的语法分析工具;
■ 扩展性,修改语法规则只要修改相应的非终结符表达式即可;
若扩展语法,则只要增加非终结符类即可;
解释器模式的缺点:
■ 解释器模式会引起类膨胀;
每个语法都要产生一个非终结符表达式,语法比较复杂时就可能产生大量的类文件,不易维护;
■ 采用递归调用方法;
每个非终结符表达式只关心与自己有关的表达式,每个表达式需要知道最终的结果,必须一层一层地剥茧,无论是面向过程的语言还是面向对象的语言,递归都是在必要条件下使用的,不易调试且影响效率;
解释器模式的使用场景:
■ 重复发生的问题可以使用解释器模式;
例如,多个应用服务器,每天产生大量的日志,需要对日志文件进行分析处理,由于各个服务器的日志格式不同,但是数据要素是相同的,按照解释器的说法就是终结符表达式都是相同的,非终结符表达式就需要制定;
■ 一个简单语法需要解释的场景;
三、解释器模式的实例
# 使用解释器模式完成四则算术运算表达式的计算;

image.png
/**
* 算术表达式,对应解释器模式中的抽象解释器角色
*/
public interface ArithmeticExpression {
int interpret(Variables variables);
}
/**
* 算术表达式中的变量,对应解释器模式中的终结符表达式
*/
public class Variable implements ArithmeticExpression{
@Override
public int interpret(Variables variables) {
return variables.get(this);
}
}
import java.util.HashMap;
import java.util.Map;
/**
* 使用Map存储各个变量的值,对应解释器模式中的环境角色
*/
public class Variables {
Map<Variable , Integer> v = new HashMap<>();
public void put(Variable variable , int value){
v.put(variable , value);
}
public int get(Variable variable){
return v.get(variable);
}
}
/**
* 加法运算 对应解释器模式中的非终结符表达式
*/
public class Plus implements ArithmeticExpression{
private ArithmeticExpression left;
private ArithmeticExpression right;
public Plus(ArithmeticExpression left, ArithmeticExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) + right.interpret(variables);
}
}
/**
* 减法运算 对应解释器模式中的非终结符表达式
*/
public class Substract implements ArithmeticExpression{
private ArithmeticExpression left;
private ArithmeticExpression right;
public Substract(ArithmeticExpression left, ArithmeticExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) - right.interpret(variables);
}
}
/**
* 乘法运算 对应解释器模式中的非终结符表达式
*/
public class Multiply implements ArithmeticExpression{
private ArithmeticExpression left;
private ArithmeticExpression right;
public Multiply(ArithmeticExpression left, ArithmeticExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) * right.interpret(variables);
}
}
/**
* 除法运算 对应解释器模式中的非终结符表达式
*/
public class Division implements ArithmeticExpression{
private ArithmeticExpression left;
private ArithmeticExpression right;
public Division(ArithmeticExpression left, ArithmeticExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpret(Variables variables) {
return left.interpret(variables) / right.interpret(variables);
}
}
/**
* 客户端应用类
*/
public class ClientDemo {
public static void main(String[] args){
Variables v = new Variables();
Variable x = new Variable();
Variable y = new Variable();
Variable z = new Variable();
v.put(x , 10);
v.put(y , 20);
v.put(z , 30);
/**
* 计算 x * (y + z / x) - x
*/
ArithmeticExpression ae = new Substract(new Multiply(x , new Plus(y , new Division(z , x))) , x);
System.out.println(ae.interpret(v));
}
}
# 控制台输出:
220
参考:
摘录 《设计模式(Java版)》韩敬海主编;(微信读书APP中有资源,可以直接阅读)
网友评论