解释器模式

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

                    语言中的句子。


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;
	}
}
扫描二维码关注公众号,回复: 816869 查看本文章
public class Main {

	public static void main(String[] args) {

		// 构建表示该文法定义的语言中一个特定的句子的抽象语法树,调用解释操作。
		Context context = new Context();
		List<AbstractExpression> list = new ArrayList<AbstractExpression>();
		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 

猜你喜欢

转载自clq9761.iteye.com/blog/1090135
今日推荐