博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解释器模式
阅读量:2433 次
发布时间:2019-05-10

本文共 4886 字,大约阅读时间需要 16 分钟。

 解释器模式:给定一个语言,定义它的文法的一种表示。并定义一个解释器,这个解释器使用该表示来解释

                    语言中的句子。

1.如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。
   这样就可以构造一个解释器,该解释器通过解释这些句子来解决该问题。
 2.当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
 3.使用解释器模式时,可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,

    可使用继承来改变或扩展该文法。  也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,

    这些类都易于直接编写。

 4.抽象语法树的每一个节点都代表一个语句,而在每个节点上都可以执行解释方法。这个解释方法的
    执行就代表这个语句被解释。
 5.一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。
 6.不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。
     建议当文法非常复杂时,使用其它的技术如语法分析程序或编译器生成器来处理。

 

/** * 抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中的所有节点所共享。 */public abstract class AbstractExpression {		public abstract void interpret(Context context);}

 

/** * 终结符表达式,实现与文法中的终结符相关联的解释操作。 * 文法中每一个终结符都有一个具体的终结表达式与之相对应。 */public class TerminalExpression extends AbstractExpression{	@Override	public void interpret(Context context) {				System.out.println("终端解释器");	}}

 

/** * 非终结符表达式,为文法中的非终结符实现解释操作。 * 对文法中的每一条规则R1,R2...Rn都需要一个具体的非终结符表达式类。 * 解释操作以递归方式调用上面所提到的代表R1,R2....Rn中的各个符号的实例变量。 */public class NonTerminalExpression extends AbstractExpression{	@Override	public void interpret(Context context) {				System.out.println("非终端解释器");	}}

 

/** * 包含解释器之外的一些全局信息。 */public class Context {		private String intput;		private String output;		public String getIntput() {		return intput;	}	public void setIntput(String intput) {		this.intput = intput;	}	public String getOutput() {		return output;	}	public void setOutput(String output) {		this.output = output;	}}

 

public class Main {	public static void main(String[] args) {		// 构建表示该文法定义的语言中一个特定的句子的抽象语法树,调用解释操作。		Context context = new Context();		List
list = new ArrayList
(); list.add(new TerminalExpression()); list.add(new NonTerminalExpression()); list.add(new TerminalExpression()); list.add(new TerminalExpression()); for(AbstractExpression expression:list){ expression.interpret(context); } }}

 

 解释器模式示例:音乐解释器事例(音符,音阶,音速等) 

 

 

 

/** * 演奏内容类 */public class PlayContext {		// 演奏文本	private String text;	public String getText() {		return text;	}	public void setText(String text) {		this.text = text;	}}

 

/** * 表达式类 */public abstract class Expression {		//解释器	public void interpret(PlayContext context){				if(context.getText().length()==0){			return;		}else{						// 获取playKey和playValue			//(例:"O 3 E 0.5 G 0.5 A 3 "playKey为O,playValue为3)			char playKey = context.getText().substring(0,1).charAt(0);			context.setText(context.getText().substring(2));			Double playValue = Double.parseDouble(context.getText()									 .substring(0,context.getText().indexOf(" ")));						// 获得playKey和playValue后,将其从演奏文本中移除			// (例:"O 3 E 0.5 G 0.5 A 3 "变成"E 0.5 G 0.5 A 3 ")			context.setText(context.getText().substring(context.getText().indexOf(" ")+1));						execute(playKey, playValue);		}	}	// 执行,抽象方法执行不同的文法子类,有不同的执行处理。	public abstract void execute(char key,Double value);}

 

 

/** * 音符类,终结符表达式 */public class Note extends Expression{	@Override	public void execute(char key, Double value) {				String note = "";		// 如果获得的key是C则演奏1(do),D则演奏2(Re)		switch(key){					case 'C':				note = "1";				break;			case 'D':				note = "2";				break;			case 'E':				note = "3";				break;			case 'F':				note = "4";				break;			case 'G':				note = "5";				break;			case 'A':				note = "6";				break;			case 'B':				note = "7";				break;					}				System.out.print(note+" ");	}}

 

/** * 音阶类,终结符表达式 */public class Scale extends Expression{	@Override	public void execute(char key, Double value) {				String scale = "";				// 如果获得的key是O并且value是1则演奏低音,2则是中音,3则是高音		switch(value.intValue()){					case 1:				scale = "低音";				break;			case 2:				scale = "中音";				break;			case 3:				scale = "高音";				break;					}				System.out.print(scale+" ");	}}

 

/** * 音速类,终结符表达式 */public class Speed extends Expression{	@Override	public void execute(char key, Double value) {				// T 1000 表示每节拍一秒,T 500 表示每节拍半秒		String speed = "";		if(value<500){			speed = "快速";		}else if(value>=1000){			speed = "慢速";		}else{			speed = "中速";		}		System.out.print(speed+" ");	}}

 

public class Main {	public static void main(String[] args) {		PlayContext context = new PlayContext();		System.out.println("上海滩:");		context.setText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3");			Expression expression = null;				try{			while (context.getText().length()>0){				char str = context.getText().substring(0,1).charAt(0);				switch (str){									case 'O':						// 当首字母是O时,表达式实例化为音阶						expression  = new Scale();						break;					case 'T':						// 当首字母是T时,表达式实例化为音速						expression  = new Speed();						break;					case 'C':					case 'D':					case 'E':					case 'F':					case 'G':						case 'A':					case 'B':									case 'P':						// 当首字母是CDEFGAB以及休止符P时,表达式实例化为音符						expression  = new Note();						break;				}								expression.interpret(context);								}		}catch(Exception e){			e.printStackTrace();		}		}}

 

 输出结果如下:

 

上海滩:中速 中音 3 5 6 3 5 5 2 3 5 6 高音 1 中音 6 5 1 3

 

转载地址:http://syxmb.baihongyu.com/

你可能感兴趣的文章
11g卸载脚本
查看>>
oracle从10.2.0.4升级到11.2.0.1的三种升级方法
查看>>
prepare statement cache size influence database
查看>>
加数据文件引起load上升
查看>>
enqueue HW wait 引起表空间突然大量扩展
查看>>
IPCS ipcrm删除信号量
查看>>
New in Mysql 5.5
查看>>
cmake指定路径
查看>>
后台跑脚本替代crontab
查看>>
10G删除空数据文件
查看>>
SSD与Fusion IO 实测随机读写 IOPS
查看>>
linux vsftpd
查看>>
CDMA蜂窝网无线定位技术的研究(转)
查看>>
与脚本病毒做斗争,几种常见的杀毒方法(转)
查看>>
详述Windows XP SP2防火墙实战策略(转)
查看>>
Jabber即时通讯客户端(三)(转)
查看>>
使用NetBeans开发MIDP应用程序(转)
查看>>
何我在asp程序内使用msgbox,程序出错说没有权限(转)
查看>>
IVR技术的发展(转)
查看>>
使用Struts的Token机制解决表单的重复提交(转)
查看>>